我已经搜索了一下,但也许我没有将正确的magik咒语放入搜索框。
有谁知道如何从Python中的存储过程获取输出参数?我正在使用pymssql来调用存储过程,而且我不确定返回输出参数的正确语法。我不认为我可以使用任何其他数据库模块,因为我从Linux机器上运行它以连接到MS服务器上的mssql数据库。
import pymssql
con = pymssql.connect(host='xxxxx',user='xxxx',password='xxxxx',database='xxxxx')
cur = con.cursor()
query = "EXECUTE blah blah blah"
cur.execute(query)
con.commit()
con.close()
答案 0 :(得分:4)
我不是python专家但是在对DB-API 2.0进行了简短的细读之后我相信你应该使用游标的“callproc”方法,如下所示:
cur.callproc('my_stored_proc', (first_param, second_param, an_out_param))
然后你将在“an_out_param”变量的返回值(out param)中得到结果。
答案 1 :(得分:2)
如果你不能或不想修改原始程序并且可以访问数据库,你可以编写一个可以从python调用的简单包装程序。
例如,如果您有一个存储过程,如:
CREATE PROC GetNextNumber
@NextNumber int OUTPUT
AS
...
你可以写一个像这样的包装器,它可以从python中轻松调用:
CREATE PROC GetNextNumberWrap
AS
DECLARE @RNextNumber int
EXEC GetNextNumber @RNextNumber
SELECT @RNextNumber
GO
然后你可以像这样从python中调用它:
import pymssql
con = pymssql.connect(...)
cur = con.cursor()
cur.execute("EXEC GetNextNumberWrap")
next_num = cur.fetchone()[0]
答案 2 :(得分:1)
如果你让你的程序产生一个表,你可以用这个结果代替out params。
所以而不是:
CREATE PROCEDURE Foo (@Bar INT OUT, @Baz INT OUT) AS
BEGIN
/* Stuff happens here */
RETURN 0
END
DO
CREATE PROCEDURE Foo (@Bar INT, @Baz INT) AS
BEGIN
/* Stuff happens here */
SELECT @Bar Bar, @Baz Baz
RETURN 0
END
答案 3 :(得分:1)
在连接到Microsoft SQL Server 7 SP3及更高版本时,看起来在freetds(pymssql,pyodbc等)之上实现的每个python dbapi库都无法访问输出参数。
答案 4 :(得分:1)
我能够使用Python从SQL存储过程中获取输出值。我找不到很好的帮助在Python中获取输出值。我自己想出了Python语法,所以我怀疑这值得在这里发布:
import sys, string, os, shutil, arcgisscripting
from win32com.client import Dispatch
from adoconstants import *
#skip ahead to the important stuff
conn = Dispatch('ADODB.Connection')
conn.ConnectionString = "Provider=sqloledb.1; Data Source=NT38; Integrated Security = SSPI;database=UtilityTicket"
conn.Open()
#Target Procedure Example: EXEC TicketNumExists @ticketNum = 8386998, @exists output
Cmd = Dispatch('ADODB.Command')
Cmd.ActiveConnection = conn
Cmd.CommandType = adCmdStoredProc
Cmd.CommandText = "TicketNumExists"
Param1 = Cmd.CreateParameter('@ticketNum', adInteger, adParamInput)
Param1.Value = str(TicketNumber)
Param2 = Cmd.CreateParameter('@exists', adInteger, adParamOutput)
Cmd.Parameters.Append(Param1)
Cmd.Parameters.Append(Param2)
Cmd.Execute()
Answer = Cmd.Parameters('@exists').Value
答案 5 :(得分:0)
您可能还会考虑使用SELECT而不是EXECUTE。 EXECUTE是(iirc)基本上是一个实际上没有取任何东西的SELECT(只会发生副作用)。
答案 6 :(得分:0)
pymssql v2.x为callproc
提供有限的支持。它使用pymssql.output()
参数语法支持OUTPUT参数。但请注意,如果存储过程不也返回结果集,则只能使用callproc
检索OUTPUT参数。该问题在GitHub上进行了讨论here。
给定T-SQL存储过程
CREATE PROCEDURE [dbo].[myDoubler]
@in int = 0,
@out int OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT @out = @in * 2;
END
Python代码
import pymssql
conn = pymssql.connect(
host=r'localhost:49242',
database='myDb',
autocommit=True
)
crsr = conn.cursor()
sql = "dbo.myDoubler"
params = (3, pymssql.output(int, 0))
foo = crsr.callproc(sql, params)
print(foo)
conn.close()
产生以下输出
(3, 6)
请注意callproc
返回参数元组,其中包含由存储过程指定的OUTPUT参数值(在这种情况下为foo[1]
)。
如果存储过程返回一个或多个结果集并且也返回输出参数,我们需要使用匿名代码块来检索输出参数值:
存储过程:
ALTER PROCEDURE [dbo].[myDoubler]
@in int = 0,
@out int OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT @out = @in * 2;
-- now let's return a result set, too
SELECT 'foo' AS thing UNION ALL SELECT 'bar' AS thing;
END
Python代码:
sql = """\
DECLARE @out_value INT;
EXEC dbo.myDoubler @in = %s, @out = @out_value OUTPUT;
SELECT @out_value AS out_value;
"""
params = (3,)
crsr.execute(sql, params)
rows = crsr.fetchall()
while rows:
print(rows)
if crsr.nextset():
rows = crsr.fetchall()
else:
rows = None
结果:
[('foo',), ('bar',)]
[(6,)]
答案 7 :(得分:0)
您可以尝试重新格式化query
:
import pypyodc
connstring = "DRIVER=SQL Server;"\
"SERVER=servername;"\
"PORT=1043;"\
"DATABASE=dbname;"\
"UID=user;"\
"PWD=pwd"
conn = pypyodbc.connect(connString)
cursor = conn.cursor()
query="DECLARE @ivar INT \r\n" \
"DECLARE @svar VARCHAR(MAX) \r\n" \
"EXEC [procedure]" \
"@par1=?," \
"@par2=?," \
"@param1=@ivar OUTPUT," \
"@param2=@svar OUTPUT \r\n" \
"SELECT @ivar, @svar \r\n"
par1=0
par2=0
params=[par1, par2]
result = cursor.execute(query, params)
print result.fetchall()
答案 8 :(得分:0)
这是我如何做到的,关键是首先声明输出参数:
import cx_Oracle as Oracle
conn = Oracle.connect('xxxxxxxx')
cur = conn.cursor()
idd = cur.var(Oracle.NUMBER)
cur.execute('begin :idd := seq_inv_turnover_id.nextval; end;', (idd,))
print(idd.getvalue())