pymsql - python mssql
¿Cómo se obtienen los parámetros de salida de un procedimiento almacenado en Python? (9)
No soy un experto en python, pero después de leer brevemente DB-API 2.0 , creo que debería usar el método "callproc" del cursor de esta manera:
cur.callproc(''my_stored_proc'', (first_param, second_param, an_out_param))
Luego tendrá el resultado en el valor devuelto (del parámetro out) en la variable "an_out_param".
Busqué en Google un poco, pero tal vez no puse el encantamiento mágico correcto en el cuadro de búsqueda.
¿Alguien sabe cómo obtener los parámetros de salida de un procedimiento almacenado en Python? Estoy usando pymssql para llamar a un procedimiento almacenado, y no estoy seguro de la sintaxis correcta para recuperar el parámetro de salida. No creo que pueda usar ningún otro módulo db ya que estoy ejecutando esto desde una caja Linux para conectarme a una base de datos mssql en un servidor MS.
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()
Si hace que su procedimiento produzca una tabla, puede usar ese resultado como sustituto de los params.
Entonces, en lugar de:
CREATE PROCEDURE Foo (@Bar INT OUT, @Baz INT OUT) AS
BEGIN
/* Stuff happens here */
RETURN 0
END
hacer
CREATE PROCEDURE Foo (@Bar INT, @Baz INT) AS
BEGIN
/* Stuff happens here */
SELECT @Bar Bar, @Baz Baz
RETURN 0
END
También puede ver usar SELECT en lugar de EXECUTE. EXECUTE es (iirc) básicamente un SELECT que en realidad no capta nada (solo hace que ocurran los efectos secundarios).
Parece que todas las bibliotecas python dbapi implementadas en la parte superior de freetds (pymssql, pyodbc, etc.) no podrán acceder a los parámetros de salida cuando se conecten a Microsoft SQL Server 7 SP3 y superior.
Si no puede o no quiere modificar el procedimiento original y tener acceso a la base de datos, puede escribir un procedimiento de contenedor simple que se pueda llamar desde Python.
Por ejemplo, si tiene un procedimiento almacenado como:
CREATE PROC GetNextNumber
@NextNumber int OUTPUT
AS
...
Podrías escribir un wrapper como tal que sea fácilmente recuperable de python:
CREATE PROC GetNextNumberWrap
AS
DECLARE @RNextNumber int
EXEC GetNextNumber @RNextNumber
SELECT @RNextNumber
GO
Entonces podrías llamarlo desde python, así:
import pymssql
con = pymssql.connect(...)
cur = con.cursor()
cur.execute("EXEC GetNextNumberWrap")
next_num = cur.fetchone()[0]
Pude obtener un valor de salida de un procedimiento almacenado de SQL usando Python. No pude encontrar una buena ayuda para obtener los valores de salida en Python. Me di cuenta de la sintaxis de Python, así que sospecho que vale la pena publicarla aquí:
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
Puede intentar reformatear la 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()
Así es como lo hice, la clave es declarar primero el parámetro de salida:
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())
Actualización de 2016 (soporte de callproc en pymssql 2.x)
pymssql v2.x ofrece soporte limitado para callproc
. Admite los parámetros OUTPUT utilizando la sintaxis del parámetro pymssql.output()
. Sin embargo, tenga en cuenta que los parámetros OUTPUT solo se pueden recuperar con callproc
si el procedimiento almacenado tampoco devuelve un conjunto de resultados. Ese problema se discute en GitHub aquí .
Para procedimientos almacenados que no devuelven un conjunto de resultados
Dado el procedimiento almacenado T-SQL
CREATE PROCEDURE [dbo].[myDoubler]
@in int = 0,
@out int OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT @out = @in * 2;
END
el código de 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()
produce la siguiente salida
(3, 6)
Observe que callproc
devuelve el parámetro tuple con el valor del parámetro OUTPUT asignado por el procedimiento almacenado ( foo[1]
en este caso).
Para procedimientos almacenados que devuelven un conjunto de resultados
Si el procedimiento almacenado devuelve uno o más conjuntos de resultados y también devuelve parámetros de salida, necesitamos usar un bloque de código anónimo para recuperar los valores del parámetro de salida:
Procedimiento almacenado:
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
Código de 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
Resultado:
[(''foo'',), (''bar'',)]
[(6,)]