Как получить выходные параметры из хранимой процедуры в Python?

Я немного погуглил, но, возможно, я не ввел правильное магическое заклинание в поле поиска.

Кто-нибудь знает, как получить выходные параметры из хранимой процедуры в Python? Я использую pymssql для вызова хранимой процедуры и не уверен в правильном синтаксисе для возврата выходного параметра. Я не думаю, что могу использовать какие-либо другие модули db, так как я запускаю их из коробки Linux для подключения к базе данных mssql на 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()
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
10
0
24 686
9

Ответы 9

Я не эксперт по питону, но после краткого ознакомления с DB-API 2.0 я считаю, что вам следует использовать метод курсора callproc следующим образом:

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

Тогда вы получите результат в виде возвращенного значения (параметра out) в переменной «an_out_param».

Ах ... к сожалению, у меня возникает эта ошибка. Похоже, что у pymssql нет callproc. AttributeError: экземпляр pymssqlCursor не имеет атрибута callproc

projecktzero 10.10.2008 22:21

Попробуйте найти другой драйвер, более совместимый с DB-API 2.0. Начать здесь - wiki.python.org/moin/SQL_Server

Milen A. Radev 10.10.2008 22:52

Похоже, он охватывает большую часть того же, что и эта ссылка: ramblings.timgolden.me.uk/2007/09/26/… Ни один из бесплатных / oss, похоже, еще не поддерживает callproc или не работает в Linux. Возможно, мне нужно будет изучить решение для веб-сервисов.

projecktzero 10.10.2008 23:21

Я думаю, что прочитал, что callproc в настоящее время не реализован для SQL Server, когда я немного погуглил по этому поводу.

Tomalak 13.10.2008 21:52

Какая библиотека не реализует callproc (кроме pymssql)? Я только что проверил источник adodbapi, и, похоже, он реализован (я на самом деле не тестировал реализацию).

Milen A. Radev 14.10.2008 01:04

Будет ли работать adodbapi в Linux? Похоже, он работает только в Windows.

projecktzero 20.10.2008 20:17

На всякий случай, если кто-то еще увидит этот ответ, вы должны передать callproc выходные параметры, обернутые следующим образом: pymssql.output (int, -1) Как описано здесь: github.com/pymssql/pymssql/blob/…

jloria 24.12.2014 05:00

Вы также можете использовать SELECT вместо EXECUTE. EXECUTE - это (iirc), по сути, SELECT, который на самом деле ничего не извлекает (просто вызывает побочные эффекты).

Если вы заставляете свою процедуру создавать таблицу, вы можете использовать этот результат в качестве замены 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

Похоже, что каждая библиотека python dbapi, реализованная поверх freetds (pymssql, pyodbc и т. д.), Не сможет получить доступ к параметрам вывода при подключении к Microsoft SQL Server 7 SP3 и выше.

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

Этот ответ устарел, по крайней мере, для pymssql.

Gord Thompson 11.10.2016 02:49

Если вы не можете или не хотите изменять исходную процедуру и иметь доступ к базе данных, вы можете написать простую процедуру-оболочку, вызываемую из 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]

Интересно, можете ли вы сделать это без вспомогательного sproc, просто с conn.execute ("DECLARE @RNextNumber int; EXEC GetNextNumber @RNextNumber out; SELECT @RNextNumber").

Constantin 24.02.2009 19:08

Мне удалось получить выходное значение из хранимой процедуры SQL с помощью Python. Мне не удалось найти хорошую помощь в получении выходных значений в 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

Обновление 2016 (поддержка callproc в pymssql 2.x)

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

Другие вопросы по теме