Ответ 1
Это необычный формат, поддерживаемый только некоторыми DBAPI, поскольку он отображает кортеж элементов как отдельных выражений SQL, включая то, что он отображает запятую и таковую между параметрами, поэтому выражение типа execute("select * from table where value in %s", (somelist, ))
расширяется на уровня базы данных в select * from table where value in (1, 2, 3)
.
SQLAlchemy не ожидает этого формата - он уже проверяет входящие параметры, поскольку он связан с маршрутизацией параметров в методы DBAPI execute()
или executemany()
, а также принимает несколько разных стилей, и Результатом этого преобразования является то, что кортеж здесь выравнивается. Вы можете прокрасть кортеж мимо этого разбора, добавив еще один кортеж:
from sqlalchemy import create_engine
engine = create_engine("postgresql://scott:[email protected]/test", echo=True)
with engine.connect() as conn:
trans = conn.begin()
conn.execute("create table test (data integer)")
conn.execute(
"insert into test (data) values (%s)",
[(1, ), (2, ), (3, ), (4, ), (5, )]
)
result = conn.execute(
"select * from test where data in %s",
(
((1, 2, 3),),
)
)
print result.fetchall()
Этот стиль работает только для некоторых файлов DBAPI. Быстрый тест подтверждает, что он работает для psycopg2 и MySQLdb, но не для sqlite3. Это больше связано с базовой системой, которую DBAPI использует для отправки связанных параметров в базу данных; psycopg2 и MySQLdb выполняют как интерполяцию строк Python, так и их собственное экранирование, но такие системы, как cx_oracle, будут передавать параметры индивидуально для OCI, поэтому в этом случае это не будет работать.
SQLAlchemy, конечно же, предлагает оператор in_() при использовании конструкторов SQL-выражений, но это не относится к прямым строкам.