如何在Python中访问带有表值参数的SQL Server 2008存储过程

7 投票
1 回答
2404 浏览
提问于 2025-04-16 16:07

我想找到一种方法,可以利用一个结果集来查找SQL Server 2008中的记录,而不是一个一个地去查。这个结果集可能有成千上万条记录。目前我在尝试用sqlite3在内存中创建一个表,然后把这个表传给一个存储过程,这个存储过程可以接受表值参数。SQL Server那边的工作已经完成,用户定义的类型也创建好了,接受表值参数的测试过程也存在,我通过TSQL测试过,似乎一切正常。在Python中,我通过sqlite3创建了一个简单的内存表。问题是,我找到的关于如何用表值参数访问存储过程的文档都是用ADO.Net和VB写的,没有Python的相关资料。不幸的是,我的编程水平还不足以进行转换。有没有人用过SQL Server的存储过程和表值参数?我还有其他方法可以尝试吗?

以下是一些链接:
关于表值参数的不错解释,以及如何在SQL和.Net中设置它们。

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

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

关于在Python中使用ADO的解释——几乎是我需要的,只是缺少结构化参数类型。
http://www.mayukhbose.com/python/ado/ado-command-3.php

我的简单代码:

--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

现在比较难的部分——Python。

以下是创建内存表的代码:

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

好的,我尝试通过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 个回答

0

我之前用过ADO.NET编写过表值参数(TVPs)。这里有一个关于经典ADO中TVPs的问题,我很感兴趣,sql server - 经典ADO和存储过程中的表值参数 - Stack Overflow。这个问题没有给出直接的答案,而是提供了一些替代方案。

  • 使用XML的选项比较简单,你可能已经考虑过了;不过这会需要更多的服务器端处理。
  • 这里有一个关于TVPs的低级ODBC编程的msdn链接。表值参数(ODBC)。如果你能切换到ODBC,这个答案是最接近的。
  • 你可以把一个csv字符串传递给nvarchar(max),然后再传递给CLR SplitString函数,这个方法很快,但有一些默认行为我不太赞同。

请在这里分享哪些方法有效,哪些无效。

撰写回答