переменная выполнения pyodbc становится @ P1 - PullRequest
0 голосов
/ 06 июня 2018

Привет, я делаю что-то вроде:

# 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.

Кто-нибудь знает, какпочини это?Любая помощь приветствуется.* 1026 Благодарения и *

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

Есть способ сделать это.Вам нужно динамически построить команду (в идеале, как строковую переменную 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 ().

0 голосов
/ 07 июня 2018

В вашем первом случае подстановка параметров не работает для имен таблиц / столбцов.Это характерно для подавляющего большинства (если не всех) платформ баз данных.

Во втором случае SQL Server не поддерживает замену параметров для операторов DDL.Драйвер ODBC для SQL Server преобразует заполнители параметра 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 (форматирование строки) для вставки соответствующих значений.

...