7
votes

I’m looking for a way to take a result set and use it to find records in a table that resides in SQL Server 2008 – without spinning through the records one at a time. The result sets that will be used to find the records could number in the hundreds of thousands. So far I am pursuing creating a table in memory using sqlite3 and then trying to feed that table to a stored procedure that takes a table valued parameter. The work on the SQL Server side is done, the user defined type is created, the test procedure accepting a table valued parameter exists and I’ve tested it through TSQL and it appears to work just fine. In Python a simple in memory table was created through sqlite3. Now the catch, the only documentation I have found for accessing a stored procedure with a table valued parameter uses ADO.Net and VB, nothing in Python. Unfortunately, I’m not enough of a programmer to translate. Has anyone used a SQL Server stored procedure with a table valued parameter? Is there another approach I should look into?

Here are some links: Decent explanation of table valued parameters and how to set them up in SQL and using in .Net

http://www.sqlteam.com/article/sql-server-2008-table-valued-parameters

http://msdn.microsoft.com/en-us/library/bb675163.aspx#Y2142

Explanation of using ADO in Python – almost what I need, just need the structured parameter type. http://www.mayukhbose.com/python/ado/ado-command-3.php

My simple code

--TSQL to create type on SQL database
create Type PropIDList as Table
(Prop_Id BigInt primary key)
--TSQL to create stored procedure on SQL database.  Note reference to 
create procedure PropIDListTest @PIDList  PropIDList READONLY
as
SET NOCOUNT ON
select * from
@PIDList p 
SET NOCOUNT OFF
--TSQL to test objects.  
--Declare variable as user defined type (table that has prop_id)
declare @pidlist as propidlist
--Populate variable
insert into @pidlist(prop_id)
values(1000)
insert into @pidlist(prop_id)
values(2000)

--Pass table variable to stored procedure
exec PropIDListTest @pidlist

Now the tough part – Python.

Here is the code creating the in memory table

import getopt, sys, string, os, tempfile, shutil
import _winreg,win32api, win32con
from win32com.client import Dispatch
from adoconstants import *
import sqlite3

conn1 = sqlite3.connect(':memory:')
c = conn1.cursor()
# Create table
c.execute('''create table PropList
        (PropID bigint)''')

# Insert a row of data
c.execute("""insert into PropList
                  values (37921019)""")

# Save (commit) the changes
conn1.commit()
c.execute('select * from PropList order by propID')
# lets print out what we have to make sure it works
for row in c:
    print row

Ok, my attempt at connecting through Python

conn = Dispatch('ADODB.Connection')
conn.ConnectionString = "Provider=sqloledb.1; Data Source=nt38; Integrated Security = SSPI;database=pubs"   
conn.Open()
cmd = Dispatch('ADODB.Command')
cmd.ActiveConnection = conn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "PropIDListTest @pidlist = ?"
param1 = cmd.CreateParameter('@PIDList', adUserDefined)  # I “think” the parameter type is the key and yes it is most likely wrong here.
cmd.Parameters.Append(param1)
cmd.Parameters.Value = conn1 # Yeah, this is probably wrong as well

(rs, status) = cmd.Execute()
while not rs.EOF:
    OutputName = rs.Fields("Prop_ID").Value.strip().upper()
    print OutputName
    rs.MoveNext()
rs.Close()
rs = None
conn.Close()
conn = None
 # We can also close the cursor if we are done with it
c.close()
conn1.close()
1
Why do you want to do that in Python? Is IronPython an option? Or are you restricted to CPython?Achim
Python is supported by our major vendor (ESRI) and they provide an add-in to Python that allows us to script spatial analysis and map production. I'm not sure arcpy will work in IronPython. If it does, then that would certainly be an option. I'll check out the ESRI for support of IronPython.Jill H
ESRI does not support IronPython.Jill H
It's been a year and still no answers. Maybe I should offer a bounty.Gabe

1 Answers

0
votes

I have coded TVPs from ADO.NET before. Here is a question on TVPs in classic ADO that I am interested in, sql server - Classic ADO and Table-Valued Parameters in Stored Procedure - Stack Overflow. It does not give a direct answer but alternatives.

  • The option of XML is easier, you have probably already considered it; it would require more server side processing.
  • Here is the msdn link for low level ODBC programming of TVPs. Table-Valued Parameters (ODBC). This one is the closest answer if you can switch to ODBC.
  • You could pass a csv string to nvarchar(max) and then pass it to a CLR SplitString function, that one is fast but has default behaviour I disagree with.

Please post back what works or does not here.