簡體   English   中英

Python中的存儲過程如何獲取output參數?

[英]How do you get output parameters from a stored procedure in Python?

我用谷歌搜索了一下,但也許我沒有在搜索框中輸入正確的魔法咒語。

有誰知道如何從Python中的存儲過程獲取output參數? 我正在使用 pymssql 調用存儲過程,但不確定返回 output 參數的正確語法。 我不認為我可以使用任何其他數據庫模塊,因為我從 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()

我不是python專家,但經過對DB-API 2.0的簡要介紹后,我相信你應該使用游標的“callproc”方法,如下所示:

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

然后你將得到“an_out_param”變量中返回值(out param)的結果。

如果您不能或不想修改原始過程並且可以訪問數據庫,則可以編寫一個可從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]

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

如果你讓你的程序產生一個表,你可以使用該結果代替out params。

所以代替:

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

看起來在連接到Microsoft SQL Server 7 SP3及更高版本時,在freetds(pymssql,pyodbc等)之上實現的每個python dbapi庫都將無法訪問輸出參數。

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

您可能還會考慮使用SELECT而不是EXECUTE。 EXECUTE是(iirc)基本上是一個實際上不會獲取任何內容的SELECT(只會產生副作用)。

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

pymssql V2.X提供了有限的支持callproc 它使用pymssql.output()參數語法支持OUTPUT參數。 但是請注意,該輸出參數只能與檢索callproc如果存儲過程還返回結果集。 這個問題在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,)]

您可以嘗試重新格式化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/

這是我如何做到的,關鍵是首先聲明輸出參數:

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

我使用 pyodbc,然后將 pyodbc 行 object 轉換為列表。 大多數答案顯示查詢聲明變量作為查詢的一部分。 但我認為您將變量聲明為 sp 的一部分,從而消除了 python 中不必要的步驟。然后,在 python 中,您所要做的就是傳遞參數以填充這些變量。

這是我用來將 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

現在,如果我需要從 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]]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM