[英]How do you get output parameters from a stored procedure in Python?
I've googled around a bit, but maybe I didn't put the correct magik incantation into the search box.我用谷歌搜索了一下,但也许我没有在搜索框中输入正确的魔法咒语。
Does anyone know how to get output parameters from a stored procedure in Python?有谁知道如何从Python中的存储过程获取output参数? I'm using pymssql to call a stored procedure, and I'm not sure of the correct syntax to get the output parameter back.
我正在使用 pymssql 调用存储过程,但不确定返回 output 参数的正确语法。 I don't think I can use any other db modules since I'm running this from a Linux box to connect to a mssql database on a MS Server.
我不认为我可以使用任何其他数据库模块,因为我从 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()
I'm not a python expert but after a brief perusing of the DB-API 2.0 I believe you should use the "callproc" method of the cursor like this: 我不是python专家,但经过对DB-API 2.0的简要介绍后,我相信你应该使用游标的“callproc”方法,如下所示:
cur.callproc('my_stored_proc', (first_param, second_param, an_out_param))
Then you'll have the result in the returned value (of the out param) in the "an_out_param" variable. 然后你将得到“an_out_param”变量中返回值(out param)的结果。
If you cannot or don't want to modify the original procedure and have access to the database you can write a simple wrapper procedure that is callable from python. 如果您不能或不想修改原始过程并且可以访问数据库,则可以编写一个可从python调用的简单包装程序。
For example, if you have a stored procedure like: 例如,如果您有一个存储过程,如:
CREATE PROC GetNextNumber
@NextNumber int OUTPUT
AS
...
You could write a wrapper like so which is easily callable from python: 你可以编写一个像这样的包装器,它可以从python中轻松调用:
CREATE PROC GetNextNumberWrap
AS
DECLARE @RNextNumber int
EXEC GetNextNumber @RNextNumber
SELECT @RNextNumber
GO
Then you could call it from python like so: 然后你可以像这样从python中调用它:
import pymssql
con = pymssql.connect(...)
cur = con.cursor()
cur.execute("EXEC GetNextNumberWrap")
next_num = cur.fetchone()[0]
I was able to get an output value from a SQL stored procedure using Python. 我能够使用Python从SQL存储过程中获取输出值。 I could not find good help getting the output values in Python.
我找不到很好的帮助在Python中获取输出值。 I figured out the Python syntax myself, so I suspect this is worth posting here:
我自己想出了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
If you make your procedure produce a table, you can use that result as a substitute for out params. 如果你让你的程序产生一个表,你可以使用该结果代替out params。
So instead of: 所以代替:
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
It looks like every python dbapi library implemented on top of freetds (pymssql, pyodbc, etc) will not be able to access output parameters when connecting to Microsoft SQL Server 7 SP3 and higher. 看起来在连接到Microsoft SQL Server 7 SP3及更高版本时,在freetds(pymssql,pyodbc等)之上实现的每个python dbapi库都将无法访问输出参数。
http://www.freetds.org/faq.html#ms.output.parameters http://www.freetds.org/faq.html#ms.output.parameters
You might also look at using SELECT rather than EXECUTE. 您可能还会考虑使用SELECT而不是EXECUTE。 EXECUTE is (iirc) basically a SELECT that doesn't actually fetch anything (, just makes side-effects happen).
EXECUTE是(iirc)基本上是一个实际上不会获取任何内容的SELECT(只会产生副作用)。
pymssql v2.x offers limited support for callproc
. pymssql V2.X提供了有限的支持
callproc
。 It supports OUTPUT parameters using the pymssql.output()
parameter syntax. 它使用
pymssql.output()
参数语法支持OUTPUT参数。 Note, however, that OUTPUT parameters can only be retrieved with callproc
if the stored procedure does not also return a result set. 但是请注意,该输出参数只能与检索
callproc
如果存储过程不还返回结果集。 That issue is discussed on GitHub here . 这个问题在GitHub上讨论了 。
Given the T-SQL stored procedure 给定T-SQL存储过程
CREATE PROCEDURE [dbo].[myDoubler]
@in int = 0,
@out int OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT @out = @in * 2;
END
the Python code 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()
produces the following output 产生以下输出
(3, 6)
Notice that callproc
returns the parameter tuple with the OUTPUT parameter value assigned by the stored procedure ( foo[1]
in this case). 请注意,
callproc
返回参数元组,其中包含由存储过程指定的OUTPUT参数值(在本例中为foo[1]
)。
If the stored procedure returns one or more result sets and also returns output parameters, we need to use an anonymous code block to retrieve the output parameter value(s): 如果存储过程返回一个或多个结果集并且还返回输出参数,我们需要使用匿名代码块来检索输出参数值:
Stored Procedure: 存储过程:
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 code: 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
Result: 结果:
[('foo',), ('bar',)]
[(6,)]
You can try to reformat query
: 您可以尝试重新格式化
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()
[1] https://amybughunter.wordpress.com/tag/pypyodbc/ [1] https://amybughunter.wordpress.com/tag/pypyodbc/
Here's how I did it, the key is to declare output parameter first: 这是我如何做到的,关键是首先声明输出参数:
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())
I use pyodbc and then convert the pyodbc rows object to a list.我使用 pyodbc,然后将 pyodbc 行 object 转换为列表。 Most of the answers show a query declaring variables as part of the query.
大多数答案显示查询声明变量作为查询的一部分。 But I would think you declare your variables as part of the sp, thus eliminating an unnecessary step in python. Then, in python, all you have to do is pass the parameters to fill in those variables.
但我认为您将变量声明为 sp 的一部分,从而消除了 python 中不必要的步骤。然后,在 python 中,您所要做的就是传递参数以填充这些变量。
Here is the function I use to convert the pyodbc rows object to a usable list (of lists) (note that I have noticed pyodbc sometimes adds trailing spaces, so I account for that which works well for me):这是我用来将 pyodbc 行 object 转换为可用列表(列表)的 function(请注意,我注意到 pyodbc 有时会添加尾随空格,因此我考虑了对我来说效果很好的那个):
def convert_pyodbc(pyodbc_lst):
'''Converts pyodbc rows into usable list of lists (each sql row is a list),
then examines each list for list elements that are strings,
removes trailing spaces, and returns a usable list.'''
usable_lst = []
for row in pyodbc_lst:
e = [elem for elem in row]
usable_lst.append(e)
for i in range(0,len(usable_lst[0])):
for lst_elem in usable_lst:
if isinstance(lst_elem[i],str):
lst_elem[i] = lst_elem[i].rstrip()
return usable_lst
Now if I need to run a stored procedure from python that returns a results set, I simply use:现在,如果我需要从 python 运行一个返回结果集的存储过程,我只需使用:
strtdate = '2022-02-21'
stpdate = '2022-02-22'
conn = mssql_conn('MYDB')
cursor = conn.cursor()
qry = cursor.execute(f"EXEC mystoredprocedure_using_dates
'{strtdate}','{stpdate}' ")
results = convert_pyodbc(qry.fetchall())
cursor.close()
conn.close()
And sample results which I then take and write to a spreadsheet or w/e:以及样本结果,然后我将其写入电子表格或 w/e:
[[datetime.date(2022, 2, 21), '723521', 'A Team Line 1', 40, 9],
[datetime.date(2022, 2, 21), '723522', 'A Team Line 2', 15, 10],
[datetime.date(2022, 2, 21), '723523', 'A Team Line 3', 1, 5],
[datetime.date(2022, 2, 21), '723686', 'B Team Line 1', 39, 27],
[datetime.date(2022, 2, 21), '723687', 'B Team Line 2', 12, 14]]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.