【问题标题】:pyodbc send parameter as nvarcharpyodbc 将参数作为 nvarchar 发送
【发布时间】:2021-12-17 21:27:22
【问题描述】:

我有一个需要使用 pyodbc 运行的带有多个参数的查询,但我遇到了问题。 这是查询的简化版,只有一个参数(我其实有6个)

declare @alertTypeName nvarchar(255)
set @alertTypeName = ?
SELECT TOP 1 Id FROM AlertType WHERE Name = @alertTypeName

@alertTypeName 可以包含特殊字符,例如“Boli şi Dăunători”。 当然,如果我直接在 SQL Server 中运行这个查询,我会设置@alertTypeName = N'Boli şi Dăunători'。如果不在文本前面添加 N,则 SELECT 不会返回任何内容。 我的问题是,如何将值作为参数发送到cursor.execute() 中的查询,以便正确编码?

这是我目前的python代码(简化版):

query = textwrap.dedent(""" 
declare @alertTypeName nvarchar(255)
set @alertTypeName = ?
SELECT TOP 1 Id FROM AlertType WHERE Name = @alertTypeName
""")

[...]
alertTypeName = "Boli şi Dăunători"

[...]
    
paramValues = [syswinAlertId, code, alertTypeName, alertMessage, createdBy, modifiedBy]
cursor.execute(query, paramValues)

alertTypeName 根据某些条件可以有不同的值,所以我不能直接将它添加到查询文本中。

【问题讨论】:

  • 我们可以假设您正在运行 Python 3.x 吗?
  • 这个link 可能会有所帮助。
  • @GordThompson 是的,我使用的是 3.8
  • @Zhorov cnxn.setencoding('utf-8') 似乎不起作用

标签: python sql sql-server parameter-passing pyodbc


【解决方案1】:

在 Python 3 中,所有字符串都是 Unicode,因此如果您将字符串作为参数值传递,那么 pyodbc 会以适当的格式将其中继到 ODBC 驱动程序管理器 (DM),以被识别为 Unicode。例如,如果我们启动 SQL Server Profiler 跟踪,然后运行此代码

cnxn = pyodbc.connect("DSN=mssqlLocal")
crsr = cnxn.cursor()
sql = "SELECT ? AS thing"
params = ("Boli şi Dăunători",)
result = crsr.execute(sql, params).fetchval()

我们将看到 SQL Server 将参数值解释为 N'string'

declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@P1 nvarchar(34)',N'SELECT @P1 AS thing',N'Boli şi Dăunători'
select @p1

请注意,我们不需要.setencoding().setdecoding() 混为一谈; pyodbc 默认值是 SQL Server 的正确值

【讨论】:

  • pyodbc 真的使用sp_prepexec 而不是sp_executesql,哇?这可以防止参数嗅探
  • @Charlieface - pyodbc 调用标准 ODBC 函数 SQLExecute。由 ODBC 驱动程序决定在后端使用哪种特定于数据库的方法。
  • 呵呵,看看它(Python)是如何在后台handles Table type parameters 然后@Charlieface。 ;)
  • 好的,我会改写一下:官方的 SQL Server ODBC 驱动程序真的使用sp_prepexec 吗? @Larnu 那太恶心了……
  • 是的,是的,@Charlieface。
【解决方案2】:

看来我的问题实际上是由代码中的错误 if 条件引起的,而不是由 SQL 引起的。感谢大家的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-03
    • 2017-11-20
    • 2012-11-01
    • 1970-01-01
    相关资源
    最近更新 更多