SQLAlchemy在INSERT中“排除”PostgreSQL命名空间... ON CONFLICT

时间:2017-07-01 20:06:26

标签: python sqlalchemy

我找不到通过SQLAlchemy执行PostgreSQL INSERT ... ON UPDATE的方法。 有没有办法用多行来做,一次对整个数据执行操作?

我尝试使用pandas数据帧中的值进行upsert:

for insert_values in df.to_dict(orient='records'):
    insert_statement = sqlalchemy.dialects.postgresql.insert(orders_to_channels).values(insert_values)
    upsert_statement = insert_statement.on_conflict_do_update(
        constraint='orders_to_channels_pkey',
    set_=insert_values
    conn.execute(upsert)

这是按行进行的,并且每行都是单独处理的 - 它的工作速度非常慢(7000行为20分钟)。 有没有办法将此操作作为单个SQL语句执行?

我正在寻找某种机会将{'column_name':'excluded .column_name'}之类的参数传递给语句的更新部分,其中“excluded”不会被解析为字符串值的一部分,而是作为一个SQL文字。有没有办法做到这一点?

1 个答案:

答案 0 :(得分:7)

使用excluded对象的特殊别名postgresql.dml.Insert

insert_statement = sqlalchemy.dialects.postgresql.insert(orders_to_channels)
upsert_statement = insert_statement.on_conflict_do_update(
    constraint='orders_to_channels_pkey',
    set_={ 'column_name': insert_statement.excluded.column_name }
)
insert_values = df.to_dict(orient='records')
conn.execute(upsert_statement, insert_values)

请注意psycopg2's executemany() is essentially equivalent to execute() in a loop,因此您可能看不到预期的性能升级。您可以尝试使用"multiple values" syntax

insert_values = df.to_dict(orient='records')
insert_statement = sqlalchemy.dialects.postgresql.insert(orders_to_channels).values(insert_values)
...

但是,that might not be any faster