我正在尝试使用sqlalchemy(版本1.0.11)在列名称中具有百分比符号的列的表上执行多插入。可以一次插入一行而不会出现问题,但是当执行带有con.execute()
OperationalError
异常的多插入时,会出现。
下面的代码重现了这个问题。创建两个表,一个在列中具有百分比名称,另一个没有。 1.列表中包含%的%的多插入失败。 2.在表中逐行插入行,列名为%in。 3.表中的多插入没有列名称中的%。
from sqlalchemy import *
USER = 'root'
PASSWORD = ''
HOST = '127.0.0.1'
DBNAME = 'test'
connect_str = "mysql://{USER}:{PASSWORD}@{HOST}/{DBNAME}".format(
USER = USER,
PASSWORD = PASSWORD,
HOST = HOST,
DBNAME = DBNAME
)
engine = create_engine(connect_str, echo = False)
metadata = MetaData()
table_with_percent = Table('table_with_percent', metadata,
Column('A%', Integer),
Column('B%', Integer)
)
table_no_percent = Table('table_no_percent', metadata,
Column('A', Integer),
Column('B', Integer)
)
metadata.create_all(engine, checkfirst = True)
#####################################
# Create rows to be inserted
rows = [(1,2), (3,4), (5,6)]
table_with_percent_rows = [dict(zip(table_with_percent.c.keys(), row)) for row in rows]
table_no_percent_rows = [dict(zip(table_no_percent.c.keys(), row)) for row in rows]
#########################
# Try the inserts
con = engine.connect()
# 1. THIS FAILS! Mutli insert on table with percentage symbol in column names.
# OperationalError: (_mysql_exceptions.OperationalError) (1054, "Unknown column 'A%%' in 'field list'") [SQL: u'INSERT INTO table_with_percent (`A%%`, `B%%`) VALUES (%s, %s)'] [parameters: ((1, 2), (3, 4), (5, 6))]
con.execute(table_with_percent.insert(), table_with_percent_rows)
# 2. But the rows can be inserted one by one:
for row in table_with_percent_rows:
con.execute(table_with_percent.insert(), row)
# 3. This works! Multi insert on table with no percent in columns
con.execute(table_no_percent.insert(), table_no_percent_rows)
con.close()
更新:我在sqlalchemy问题跟踪器上打开了this问题。
答案 0 :(得分:1)
警告在列/表名称中使用精美字符(除A-Z
,0-9
和_
之外的任何字符)是您自己拍摄的保证方法之一在脚下。
TL; DR 这似乎是SQLAlchemy中的一个错误。它错误地转义了名称中包含%
的列。您可以转到issue tracker并报告错误(如果尚未报告)。
您希望在do_execute()
sqlalchemy.engine.default.DefaultDialect
方法中添加断点。它是您的查询和参数从SA传递到数据库驱动程序的位置。在您的情况下,SQL看起来像这样:
INSERT INTO table_with_percent (`A%%`, `B%%`) VALUES (%s, %s)
是的,SQLAlchemy在列名中添加了第二个%
。这显然使列无效。您最好在问题跟踪器上询问其发生的原因。
由于幸运的巧合,插入一行是有效的。 "%s" % ("value",)
语法用于将参数格式化为查询。格式字符串%%
是转义%
字符的方法,因此在格式化查询后返回正确的格式:
INSERT INTO table_with_percent (`A%`, `B%`) VALUES (1, 2)
如果插入多行,幸运巧合不会发生,因为参数的格式化是不同的。最后您得到以下查询:
INSERT INTO table_with_percent (`A%%`, `B%%`) VALUES (1, 2), (3, 4), (5, 6)
显然失败了。
PS您可以使用以下语法使其正常工作:
con.execute(table_with_percent.insert().values(table_with_percent_rows))