11

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

有谁知道如何从 Python 中的存储过程中获取输出参数?我正在使用 pymssql 调用存储过程,但我不确定获取输出参数的正确语法。我认为我不能使用任何其他 db 模块,因为我是从 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()
4

10 回答 10

4

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

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

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

于 2008-10-10T15:59:36.020 回答
3

如果您不能或不想修改原始过程并有权访问数据库,则可以编写一个可从 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]
于 2008-10-20T22:22:29.393 回答
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
于 2009-10-20T17:58:40.350 回答
1

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

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

于 2008-10-20T21:32:53.347 回答
1

如果您让您的程序生成一个表格,您可以使用该结果代替 out 参数。

所以而不是:

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
于 2008-10-13T17:34:14.470 回答
1

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 参数值(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-10-10T23:42:58.560 回答
0

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

于 2008-10-13T17:26:58.650 回答
0

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

这是我用来将 pyodbc 行对象转换为可用列表(列表)的函数(请注意,我注意到 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]]
于 2022-02-28T17:00:49.993 回答
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())
于 2016-11-30T02:17:48.790 回答
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()

[1] https://amybughunter.wordpress.com/tag/pypyodbc/

于 2016-11-16T11:49:51.507 回答