sql-server - Pyodbc 调用带参数的存储过程
问题描述
我一直试图用参数调用这个存储过程,但无济于事。我想我已经弄清楚了参数部分,但现在我认为我只是简单地将存储过程称为错误。我试图用他们的错误消息(如下)尽可能地记录我的不同方法。如何调用带有参数的存储过程并写入数据帧?
尝试 A:使用占位符加入字典中的参数和变量的 %s
params1 = {'mo1_start_date' : '12/30/2019', 'mo1_end_date' : '01/26/2020'}
placeholders = ','.join('?' for i in range(len(params1.values()))) # '?,?'
interconnectmo1 = """exec TNT.dbo.abc \
@start_date = %(mo1_start_date)s -- datetime \
, @end_date = %(mo1_end_date)s -- datetime \
, @syscode = NULL -- varchar(8000) \
, @estimate_ids = NULL -- varchar(8000)""" %placeholders
sqlmo1 = pd.read_sql(interconnectmo1, conn, params1)
错误 A:TypeError:格式需要映射
尝试 B:没有占位符加入字典中的参数和?对于变量
params1 = {'mo1_start_date' : '12/30/2019', 'mo1_end_date' : '01/26/2020'}
interconnectmo1 = """exec TNT.dbo.abc\
@start_date = ? -- datetime \
, @end_date = ? -- datetime \
, @syscode = NULL -- varchar(8000) \
, @estimate_ids = NULL -- varchar(8000)"""
sqlmo1 = pd.read_sql(interconnectmo1, conn, params1)
错误 B:[ODBC SQL Server 驱动程序]COUNT 字段不正确或语法错误 (0) (SQLExecDirectW)
尝试 C:使用占位符加入列表中的参数和变量的 %s
params1 = {'mo1_start_date' : '12/30/2019', 'mo1_end_date' : '01/26/2020'}
paramsmo1=list(params1.values())
placeholders = ','.join('?' for i in range(len(paramsmo1))) # '?,?'
interconnectmo1 = """exec TNT.dbo.abc\
@start_date = %(mo1_start_date)s -- datetime \
, @end_date = %(mo1_end_date)s -- datetime \
, @syscode = NULL -- varchar(8000) \
, @estimate_ids = NULL -- varchar(8000)""" %placeholders
sqlmo1 = pd.read_sql(interconnectmo1, conn, paramsmo1)
错误 C:TypeError:格式需要映射
尝试 D:没有占位符加入字典中的参数和变量的 %s
params1 = {'mo1_start_date' : '12/30/2019', 'mo1_end_date' : '01/26/2020'}
interconnectmo1 = """exec TNT.dbo.abc\
@start_date = "%(mo1_start_date)s" -- datetime \
, @end_date = "%(mo1_end_date)s" -- datetime \
, @syscode = NULL -- varchar(8000) \
, @estimate_ids = NULL -- varchar(8000)""" % (params1)
sqlmo1 = pd.read_sql(interconnectmo1, conn, params1)
错误 D:过程或函数需要未提供的参数“@end_date”。
尝试 E:尝试使用光标..
params1 = {'mo1_start_date' : '12/30/2019', 'mo1_end_date' : '01/26/2020'}
csr = conn.cursor()
interconnectmo1 = csr.execute("""exec TNT.dbo.abc \
@start_date = "%(mo1_start_date)s" -- datetime \
, @end_date = "%(mo1_end_date)s" -- datetime \
, @syscode = NULL -- varchar(8000) \
, @estimate_ids = NULL -- varchar(8000)""" % (params1))
csr.execute(interconnectmo1, (params1))
错误 E:过程或函数需要未提供的参数“@end_date”。
解决方案
我终于让这个工作了。这段代码有两个问题。
- 数据类型注释标注。
-- datetime
并且-- varchar(8000)
是一个问题。即使我的代码识别了第一个参数,由于这种中断,它也找不到第二个参数。 - 作为参数的字典输入不起作用。我不确定它是否不是一种能力,或者我只是没有得到正确的语法来让它工作,但它没有工作。我也研究了绑定参数 - 没有雪茄。我什至尝试了列表输入,但没有成功。
mo1_start_date='12/30/2019'
mo1_end_date='1/26/2020'
interconnectmo1 = """exec TNT.dbo.abc
@start_date = ? , @end_date = ? , @syscode = NULL , @estimate_ids = NULL"""
sqlmo1 = pd.read_sql_query(interconnectmo1, conn, params=(mo1_start_date, mo1_end_date))
最直接的方式获胜。根本没有必要使这复杂化。如果您有字典并且无法以这种格式获取参数,那么我想您将被迫为字典寻找解决方案。但是对于这个问题,我是不必要地创建字典的人。我只是用一种更简单的方式来定义我的参数和中提琴。
我希望这对某人有所帮助,因为我花了几天时间和几个代码板最终放弃了我之前的方法来找到这个获胜的方法!
推荐阅读
- javascript - 错误:未指定默认引擎且未提供扩展(将应用程序部署到 Heroku)
- pandas - pandas datareader - 如何发送 quandl api 密钥?
- mysql - Ruby on Rails 需要 libmysqlclient.so.20 但我有 21... 需要降级?
- regex - 如何仅在包含 SUM 中包含字符串的单元格的行上使用 REGEXEXTRACT?
- matlab - 子图中的电影比例 - Matlab
- java - 我的小组遇到了问题,其中一个人发送了他的部分,但是有一个 ArrayIndexOutOfBounds 错误,但我没有看到问题
- laravel - Laravel 代客安装失败
- javascript - 如何动态创建按钮?
- react-big-calendar - 设置 scrollToTime 使日历在调整大小或拖放时松开当前滚动位置
- javascript - 有没有更高效的方式来遍历这个数组?(JavaScript)