pyodbc执行变量变为@ P1

时间:2018-06-06 20:00:56

标签: python sql-server pyodbc execute

嗨,我正在做类似的事情:

# pyodbc extension
cursor.execute("select a from tbl where b=? and c=?", x, y)

- 查询中的某些值由变量提供。但有时变量在查询中被解释为@P1

例如:

import pyodbc

ch = pyodbc.connect('DRIVER={SQL Server};SERVER=xxxx;DATABASE=xxx;Trusted_Connection=True')
cur = ch.cursor()

x = 123

cur.execute('''
CREATE TABLE table_? (
  id int IDENTITY(1,1) PRIMARY KEY,
  obj varchar(max) NOT NULL
)
''', x).commit()

这会产生一个名为table_@P1的新表(我希望table_123

另一个例子:

x = 123

cur.execute('''
CREATE TABLE table_2 (
  id int IDENTITY(1,1) PRIMARY KEY,
  obj varchar(?) NOT NULL
)
''', x).commit()

报告错误:

  

ProgrammingError:('42000',“[42000] [Microsoft] [ODBC SQL Server   驱动程序] [SQL Server]'@ P1'附近的语法不正确。 (102)   (SQLExecDirectW)“)

同样,该变量被解释为@P1

任何人都知道如何解决这个问题?任何帮助表示赞赏。谢谢 -

2 个答案:

答案 0 :(得分:3)

在第一种情况下,参数替换不适用于表/列名称。这对绝大多数(如果不是全部)数据库平台来说都很常见。

在第二种情况下,SQL Server似乎不支持DDL语句的参数替换。 SQL Server ODBC驱动程序将pyodbc参数占位符(?)转换为T-SQL参数占位符(@P1@P2,...),以便传递给SQL Server的语句

CREATE TABLE table_2 (id int IDENTITY(1,1) PRIMARY KEY, obj varchar(@P1) NOT NULL

具体地

exec sp_prepexec @p1 output,N'@P1 int',N'CREATE TABLE table_2 (id int IDENTITY(1,1) PRIMARY KEY, obj varchar(@P1) NOT NULL',123

当SQL Server尝试准备该语句时,它需要一个文字值,而不是参数占位符。

因此,在这两种情况下,您都需要使用动态SQL(字符串格式化)来插入适当的值。

答案 1 :(得分:1)

有办法做这种事情。您需要做的是动态构建命令(理想情况下为nvarchar(MAX),而不是varchar(MAX))字符串变量,并将该变量传递给cur.execute() - 或任何其他 - 命令。相应地修改您的第一个示例:

Content
顺便说一下,如果只是为了避免像这样的问题,你不应该尝试在一行中做所有事情。我还建议在你的连接字符串中添加“autocommit = True”,这样你就不必将.commit()附加到cur.execute()。