嗨,我正在做类似的事情:
# 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
。
任何人都知道如何解决这个问题?任何帮助表示赞赏。谢谢 -
答案 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()。