如何从 Python 中的存储过程获取输出参数?

发布于 2024-07-07 19:38:01 字数 400 浏览 6 评论 0原文

我用谷歌搜索了一下,但也许我没有在搜索框中输入正确的魔法咒语。

有谁知道如何从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()

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? I'm using pymssql to call a stored procedure, and I'm not sure of the correct syntax to get the output parameter back. 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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

清醇 2024-07-14 19:38:01

我不是 python 专家,但在简要阅读了 DB-API 2.0< /a> 我相信您应该像这样使用游标的“callproc”方法:

cur.callproc('my_stored_proc', (first_param, second_param, an_out_param))

然后您将在“an_out_param”变量的返回值(输出参数)中得到结果。

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:

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.

旧梦荧光笔 2024-07-14 19:38:01

如果您不能或不想修改原始过程并有权访问数据库,您可以编写一个可从 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]

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.

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:

CREATE PROC GetNextNumberWrap
AS
    DECLARE @RNextNumber int
    EXEC GetNextNumber @RNextNumber
    SELECT @RNextNumber
GO

Then you could call it from python like so:

import pymssql
con = pymssql.connect(...)
cur = con.cursor()
cur.execute("EXEC GetNextNumberWrap")
next_num = cur.fetchone()[0]
想你只要分分秒秒 2024-07-14 19:38:01

如果您让过程生成一个表,则可以使用该结果代替输出参数。

所以而不是:

CREATE PROCEDURE Foo (@Bar INT OUT, @Baz INT OUT) AS
BEGIN
   /* Stuff happens here */
   RETURN 0
END

CREATE PROCEDURE Foo (@Bar INT, @Baz INT) AS
BEGIN
   /* Stuff happens here */
   SELECT @Bar Bar, @Baz Baz
   RETURN 0
END

If you make your procedure produce a table, you can use that result as a substitute for 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
傲世九天 2024-07-14 19:38:01

看起来在 freetds 之上实现的每个 python dbapi 库(pymssql、pyodbc 等)在连接到 Microsoft SQL Server 7 SP3 及更高版本时将无法访问输出参数。

http://www.freetds.org/faq.html#ms.output。参数

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.

http://www.freetds.org/faq.html#ms.output.parameters

江湖彼岸 2024-07-14 19:38:01

我能够使用 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

I was able to get an output value from a SQL stored procedure using Python. I could not find good help getting the output values in Python. I figured out the Python syntax myself, so I suspect this is worth posting here:

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
世界和平 2024-07-14 19:38:01

2016 更新(pymssql 2.x 中的 callproc 支持)

pymssql v2.x 为 callproc 提供有限支持。 它支持使用 pymssql.output() 参数语法的 OUTPUT 参数。 但请注意,如果存储过程也返回结果集,则只能使用callproc 检索OUTPUT 参数。 该问题在 GitHub 此处 上进行了讨论。

对于不返回结果集的存储过程

给定 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 参数值 (<在本例中为 code>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,)]

2016 update (callproc support in pymssql 2.x)

pymssql v2.x offers limited support for callproc. It supports OUTPUT parameters using the pymssql.output() parameter syntax. Note, however, that OUTPUT parameters can only be retrieved with callproc if the stored procedure does not also return a result set. That issue is discussed on GitHub here.

For stored procedures that do not return a result set

Given the T-SQL stored procedure

CREATE PROCEDURE [dbo].[myDoubler] 
    @in int = 0, 
    @out int OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    SELECT @out = @in * 2;
END

the Python code

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

For stored procedures that return a result set

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:

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,)]
温柔少女心 2024-07-14 19:38:01

您可能还会考虑使用 SELECT 而不是 EXECUTE。 EXECUTE 基本上是一个 SELECT,它实际上并不获取任何内容(只会产生副作用)。

You might also look at using SELECT rather than EXECUTE. EXECUTE is (iirc) basically a SELECT that doesn't actually fetch anything (, just makes side-effects happen).

绝不放开 2024-07-14 19:38:01

您可以尝试重新格式化查询

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/

You can try to reformat 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/

貪欢 2024-07-14 19:38:01

我是这样做的,关键是先声明输出参数:

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

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())
烟雨凡馨 2024-07-14 19:38:01

我使用 pyodbc,然后将 pyodbc rows 对象转换为列表。 大多数答案都显示一个将变量声明为查询一部分的查询。 但我认为你将变量声明为 sp 的一部分,从而消除了 python 中不必要的步骤。 然后,在Python中,您所要做的就是传递参数来填充这些变量。

这是我用来将 pyodbc rows 对象转换为可用列表(列表)的函数(请注意,我注意到 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

现在,如果我需要运行来自 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()

和示例结果,然后将其写入电子表格或 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]]

I use pyodbc and then convert the pyodbc rows object to a list. 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.

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

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:

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:

[[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]]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文