Sqlalchemy 多次插入失败,列名中带有百分比符号 (%)

Man*_*nds 6 python sqlalchemy

我正在尝试使用 sqlalchemy(版本 1.0.11)对列名中带有百分比符号的列执行多插入。行可以被插入一个在没有问题的时刻,但是当执行多刀片与con.execute()一个OperationalError异常。

下面的代码重现了这个问题。创建了两个表,一个在列中有百分比名称,另一个没有。

  1. 列名中带有 % 的表上的多重插入失败。
  2. 在列名中使用 % 在表中一一插入行是有效的。
  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]
    
Run Code Online (Sandbox Code Playgroud)

尝试插入

con = engine.connect()
Run Code Online (Sandbox Code Playgroud)

这失败了!在列名称中使用百分比符号在表上插入多处。

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)
Run Code Online (Sandbox Code Playgroud)

但是可以一一插入行:

for row in table_with_percent_rows:
    con.execute(table_with_percent.insert(), row)
Run Code Online (Sandbox Code Playgroud)

这有效!在表上多次插入,列中没有百分比

con.execute(table_no_percent.insert(), table_no_percent_rows)
con.close()
Run Code Online (Sandbox Code Playgroud)

更新:我用 sqlalchemy 问题跟踪器打开了这个问题。

Yar*_*min 2

警告在列/表名称中使用花哨的字符(除A-Z,0-9和之外的任何_字符)是搬起石头砸自己脚的保证方法之一。

TL;DR这似乎是 SQLAlchemy 中的一个错误。它错误地转义了%名称为 in 的列。您可以转到问题跟踪器并报告错误(如果尚未报告)。

do_execute()您想在 的方法中放置一个断点sqlalchemy.engine.default.DefaultDialect。在这里,您的查询和参数从 SA 传递到数据库驱动程序。在你的例子中,SQL 看起来像这样:

INSERT INTO table_with_percent (`A%%`, `B%%`) VALUES (%s, %s)
Run Code Online (Sandbox Code Playgroud)

是的,SQLAlchemy%在列名称中添加了第二个。这显然会使列无效。您最好在问题跟踪器上询问为什么会发生这种情况。

由于幸运的巧合,插入单行就可以了。"%s" % ("value",)语法用于将参数格式化为查询。并且格式字符串中%%是转义字符的方式%,所以格式化后查询返回到正确的形式:

INSERT INTO table_with_percent (`A%`, `B%`) VALUES (1, 2)
Run Code Online (Sandbox Code Playgroud)

如果插入多行,则不会发生幸运的巧合,因为参数的格式设置不同。您最终会得到以下查询:

INSERT INTO table_with_percent (`A%%`, `B%%`) VALUES (1, 2), (3, 4), (5, 6)
Run Code Online (Sandbox Code Playgroud)

这显然失败了。

PS 您可以使用以下语法来使其工作:

con.execute(table_with_percent.insert().values(table_with_percent_rows))
Run Code Online (Sandbox Code Playgroud)