使用Python的SQL Server存储过程(pyodbc)

bar*_*ezr 13 python sql-server pyodbc

我有一个存储过程,代码:

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)
Run Code Online (Sandbox Code Playgroud)

我如何使用此过程创建一个原始的SQL查询来创建帐户?我正在使用烧瓶和pyodbc.

dir*_*irn 10

来自pyodbc文档

要立即调用存储过程,请使用数据库识别的格式或使用ODBC调用转义格式将调用传递给execute方法.(然后,ODBC驱动程序将重新格式化调用以匹配给定的数据库.)

对于SQL Server,您可以使用以下内容:

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

# ODBC format
cursor.execute("{call sp_dosomething(123, 'abc')}")
Run Code Online (Sandbox Code Playgroud)

所以打电话给你的程序

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))
Run Code Online (Sandbox Code Playgroud)

  • 这里有一个问题:sqlalchemy.exc.ProgrammingError: (ProgrammingError) ('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]'@P1' 附近的语法不正确。(102) (SQLExecDirectW)" ) 'exe my_procedure(?, ?, ?)' ('5215125', '125151', '31231') (2认同)
  • 谢谢,sql = 'exec [my_database].[dbo].[my_table] ?, ?, ?, ?, ?, ?, ?, ?' 工作正常(没有括号)。 (2认同)

Gor*_*son 8

接受的答案没有解决从存储过程中捕获返回值的问题,可以这样做:

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]
Run Code Online (Sandbox Code Playgroud)


小智 6

为了清楚起见,Gord 的另一种回答是使用 OUTPUT 和命名参数(在存储过程中定义)。

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()
Run Code Online (Sandbox Code Playgroud)


小智 5

不要忘记在存储过程中将SET NOCOUNT ON设置为ON。


小智 5

在到处搜索这个解决方案后,我找不到简化版本。所有的结果似乎都让这本应该很容易做到的事情变得过于复杂。这是我的解决方案。

 import pyodbc
 import pandas as pd
 import datetime as d


  conn = pyodbc.connect('Driver=;'
                  'Server=;'
                  'Database=;'
                  'UID=;'
                  'PWD=;')


     # define parameters to be passed in and out

     quarter_date = d.date(year=2020, month=10, day=1)

     SQL = r'exec TERRITORIES_SP @quarterStart = ' + "'" + str(quarter_date) + "'"

     print(SQL)

     try:
         cursor = conn.cursor()
          cursor.execute(SQL)
          cursor.close()
          conn.commit()
    finally:
          conn.close()
Run Code Online (Sandbox Code Playgroud)