pyodbc 执行变量变为@P1
pyodbc execute variable becomes @P1
嗨,我正在做类似的事情:
# 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(我想要 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
Driver][SQL Server]Incorrect syntax near '@P1'. (102)
(SQLExecDirectW)")
同样,变量被解释为 @P1
。
有人知道如何解决这个问题吗?任何帮助表示赞赏。谢谢-
在您的第一种情况下,参数替换不适用于 table/column 个名称。这对于绝大多数(如果不是全部)数据库平台都是常见的。
在你的第二种情况下,SQL 服务器似乎不支持 DDL 语句的参数替换。 SQL 服务器 ODBC 驱动程序将 pyodbc 参数占位符 (?
) 转换为 T-SQL 参数占位符 (@P1
, @P2
, ...) 因此传递给 SQL 服务器的语句是
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 服务器尝试准备该语句时,它需要一个文字值,而不是参数占位符。
因此,在这两种情况下,您都需要使用动态 SQL(字符串格式)来插入适当的值。
有一种方法可以做到这一点。您需要做的是动态构建命令(理想情况下作为 nvarchar(MAX),而不是 varchar(MAX))字符串变量并将该变量传递给 cur.execute() - 或任何其他 - 命令。相应地修改您的第一个示例:
ch = pyodbc.connect( 'DRIVER={SQL Server};SERVER=xxxx;DATABASE=xxx;Trusted_Connection=True' )
cur = ch.cursor()
x = 123
SQL_Commands = 'CREATE TABLE table_' + str( x ) + '''
(
id int IDENTITY(1,1) PRIMARY KEY,
obj varchar(max) NOT NULL
) '
'''
cur.execute( SQL_Commands ).commit()
顺便说一句,你不应该试图在一行中做所有事情,如果只是为了避免像这样的问题。我还建议考虑将 "autocommit=True" 添加到您的连接字符串,这样您就不必将 .commit() 附加到 cur.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(我想要 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 Driver][SQL Server]Incorrect syntax near '@P1'. (102) (SQLExecDirectW)")
同样,变量被解释为 @P1
。
有人知道如何解决这个问题吗?任何帮助表示赞赏。谢谢-
在您的第一种情况下,参数替换不适用于 table/column 个名称。这对于绝大多数(如果不是全部)数据库平台都是常见的。
在你的第二种情况下,SQL 服务器似乎不支持 DDL 语句的参数替换。 SQL 服务器 ODBC 驱动程序将 pyodbc 参数占位符 (?
) 转换为 T-SQL 参数占位符 (@P1
, @P2
, ...) 因此传递给 SQL 服务器的语句是
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 服务器尝试准备该语句时,它需要一个文字值,而不是参数占位符。
因此,在这两种情况下,您都需要使用动态 SQL(字符串格式)来插入适当的值。
有一种方法可以做到这一点。您需要做的是动态构建命令(理想情况下作为 nvarchar(MAX),而不是 varchar(MAX))字符串变量并将该变量传递给 cur.execute() - 或任何其他 - 命令。相应地修改您的第一个示例:
ch = pyodbc.connect( 'DRIVER={SQL Server};SERVER=xxxx;DATABASE=xxx;Trusted_Connection=True' )
cur = ch.cursor()
x = 123
SQL_Commands = 'CREATE TABLE table_' + str( x ) + '''
(
id int IDENTITY(1,1) PRIMARY KEY,
obj varchar(max) NOT NULL
) '
'''
cur.execute( SQL_Commands ).commit()
顺便说一句,你不应该试图在一行中做所有事情,如果只是为了避免像这样的问题。我还建议考虑将 "autocommit=True" 添加到您的连接字符串,这样您就不必将 .commit() 附加到 cur.execute()。