嗨,我正在做一些类似这样的事情:
# 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',“'@P1‘附近的42000ODBC SQL Server DriverIncorrect语法。(42000) (SQLExecDirectW)")
同样,该变量被解释为@P1
。
有人知道怎么解决这个问题吗?任何帮助我们都会很感激。谢谢-
发布于 2018-06-07 05:09:38
在第一种情况下,参数替换不适用于表/列名称。这在绝大多数(如果不是所有的)数据库平台上都是常见的。
在第二种情况下,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 (字符串格式化)来插入适当的值。
发布于 2018-06-08 06:17:40
有一种方法可以做到这一点。您需要做的是动态构建命令(理想情况下作为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()中。
https://stackoverflow.com/questions/50728621
复制相似问题