web-dev-qa-db-fra.com

Utilisation de procédures stockées SQL Server à partir de Python (pyodbc)

J'ai une procédure stockée, code:

DECLARE @RC int 
DECLARE @id varchar(13) 
DECLARE @pw varchar(13) 
DECLARE @depart varchar(32) 
DECLARE @class varchar(12) 
DECLARE @name varchar(12) 
DECLARE @birthday varchar(10) 
DECLARE @grade int 
DECLARE @subgrade int 
SELECT @id = 'test' 
SELECT @pw = '12345' 
SELECT @depart = 'none' 
SELECT @class = 'GM' 
SELECT @name = 'name' 
SELECT @birthday = 'None' 
SELECT @grade = 3 
SELECT @subgrade = 2 
EXEC @RC = [my_database].[dbo].[my_table] @id, @pw, @depart, @class, @name, @birthday, @grade, @subgrade 
DECLARE @PrnLine nvarchar(4000) 
PRINT 'Stored Procedure: my_database.dbo.my_table' 
SELECT @PrnLine = ' Return Code = ' + CONVERT(nvarchar, @RC)

Comment puis-je faire une requête SQL brute pour créer un compte en utilisant cette procédure? J'utilise flask et pyodbc.

15
bartezr

De la documentation pyodbc

Pour appeler une procédure stockée maintenant, passez l'appel à la méthode execute en utilisant soit un format reconnu par votre base de données, soit en utilisant le format d'échappement d'appel ODBC . (Le pilote ODBC reformatera alors l'appel pour que vous puissiez correspondre à la base de données donnée.)

Pour SQL Server, vous utiliseriez quelque chose comme ceci:

# SQL Server format
cursor.execute("exec sp_dosomething(123, 'abc')")

# ODBC format
cursor.execute("{call sp_dosomething(123, 'abc')}")

Donc, pour appeler votre procédure

id_ = 'test' 
pw = '12345' 
depart = 'none' 
class_ = 'GM' 
name = 'name' 
birthday = 'None' 
grade = 3 
subgrade = 2 

sql = 'exec [my_database].[dbo].[my_table](?, ?, ?, ?, ?, ?, ?, ?)'
values = (id_, pw, depart, class_, name, birthday, grade, subgrade)

cursor.execute(sql, (values))
9
dirn

La réponse acceptée ne résout pas le problème de la capture de la valeur de retour de la procédure stockée, ce qui peut être fait comme ceci:

id_ = 'test' 
pw = '12345' 
depart = 'none' 
class_ = 'GM' 
name = 'name' 
birthday = 'None' 
grade = 3 
subgrade = 2 

sql = """\
DECLARE @RC int;
EXEC @RC = [my_database].[dbo].[my_sp] ?, ?, ?, ?, ?, ?, ?, ?;
SELECT @RC AS rc;
"""
values = (id_, pw, depart, class_, name, birthday, grade, subgrade)
cursor.execute(sql, values)
rc = cursor.fetchval()  # pyodbc convenience method similar to cursor.fetchone()[0]
8
Gord Thompson

N'oubliez pas SET NOCOUNT ON dans votre procédure stockée.

5
Eman4real

Une autre variante de la réponse de Gord est d'utiliser OUTPUT et les paramètres nommés (à définir dans la procédure stockée) pour plus de clarté.

id_ = 'test' 
pw = '12345' 
depart = 'none' 
class_ = 'GM' 
name = 'name' 
birthday = 'None' 
grade = 3 
subgrade = 2 

sql = """\
DECLARE @RC int;
EXEC [my_database].[dbo].[my_sp] @RC OUTPUT, @id_=?, @pw=?, @depart=?, @class_=?, @name=?, @birthday=?, @grade=?, @subgrade=?;
SELECT @RC AS rc;
"""
values = (id_, pw, depart, class_, name, birthday, grade, subgrade)
cursor.execute(sql, values)
rc = cursor.fetchval()
2
Viggos

Avec un curseur initialisé par votre connexion, le sp peut être appelé directement comme suit

sql = " exec your_SP @codemp = ?, @fecha = ? "
prm = (dict['param1'], dict['param2'])
cursor.execute(qry, params)
1
Leonardo Pascual