在sqlalchemy中的Postgresql ON CONFLICT

pur*_*ion 15 python sql postgresql sqlalchemy

我读过不少资源(AO.1,2),但我无法得到PostgreSQL关于冲突忽略行为SQLAlchemy的工作.

我用这个被接受的答案作为基础,但它给出了

SAWarning: Can't validate argument 'append_string'; can't locate any SQLAlchemy dialect named 'append'
Run Code Online (Sandbox Code Playgroud)

我已经尝试将postgresql方言添加到@compile子句,重命名我的对象,但它不起作用.我也尝试使用str(insert())+ " ON CONFILCT IGNORE"没有结果.(顺便说一句,这并不奇怪)

如何才能将On CONFLICT IGNORE其添加到插入中?我喜欢建议的解决方案,因为我可以看到自己不想要IGNORE每个人的行为INSERT

PS.使用python 2.7(不介意升级到3.4/3.5),最新的sqlalchemy(1.x)

Ita*_*vni 19

使用Postgres 9.6.1,sqlachemy 1.1.4和psycopg2 2.6.2:

  1. 将数据结构转换为字典.从熊猫那里来的

    import pandas
    from sqlalchemy import MetaData
    from sqlalchemy.dialects.postgresql import insert
    import psycopg2
    
    # The dictionary should include all the values including index values
    insrt_vals = df.to_dict(orient='records')
    
    Run Code Online (Sandbox Code Playgroud)
  2. 通过sqlalchemy连接到数据库

    results = engine.execute(do_nothing_stmt)
    # Get number of rows inserted
    rowcount = results.rowcount
    
    Run Code Online (Sandbox Code Playgroud)
  3. NaT被调用者构造insert语句NaT

    tst_df = pd.DataFrame({'colA':['a','b','c','a','z', 'q'],
                  'colB': pd.date_range(end=datetime.datetime.now() , periods=6),
                  'colC' : ['a1','b2','c3','a4','z5', 'q6']})
    
    
    insrt_vals = tst_df.to_dict(orient='records')
    engine =      sqlalchemy.create_engine("postgresql://user:password@localhost/postgres")
    connect = engine.connect()
    meta = MetaData(bind=engine)
    meta.reflect(bind=engine)
    table = meta.tables['tstbl']
    insrt_stmnt = insert(table).values(insrt_vals)
    
    do_nothing_stmt  = insrt_stmnt.on_conflict_do_nothing(index_elements=['colA','colB'])
    results = engine.execute(do_nothing_stmt)
    
    Run Code Online (Sandbox Code Playgroud)
  4. 执行

    import pandas
    from sqlalchemy import MetaData
    from sqlalchemy.dialects.postgresql import insert
    import psycopg2
    
    # The dictionary should include all the values including index values
    insrt_vals = df.to_dict(orient='records')
    
    Run Code Online (Sandbox Code Playgroud)

警告:

NaT开箱即用的方法无法使用此方法.

一切都在一起

results = engine.execute(do_nothing_stmt)
# Get number of rows inserted
rowcount = results.rowcount
Run Code Online (Sandbox Code Playgroud)


小智 12

这适用于 Postgresql 10.5 和 Sqlalchemy 1.3.6:

from sqlalchemy.dialects.postgresql import insert


table_info = {
'tableTime': '',
'deploymentID': '',
'tableData': ''
}
insert_table = insert(Table).values(table_info)
insert_table_sql = insert_table.on_conflict_do_nothing(
  index_elements=['tableTime', 'deploymentID']
)
db.session.execute(insert_table_sql)
db.session.commit()
Run Code Online (Sandbox Code Playgroud)


Nik*_*s B 6

这适用于 Postgresql 9.5:

from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import Insert

@compiles(Insert)
def prefix_inserts(insert, compiler, **kw):
    return compiler.visit_insert(insert, **kw) + " ON CONFLICT DO NOTHING"
Run Code Online (Sandbox Code Playgroud)

我用它来bulk_insert_mappings。然而,它并没有使ON CONFLICT DO NOTHING可选


Ada*_*nko 5

您不需要这样做,请使用exist条件防止插入重复项。

例如:

INSERT INTO table (unique_name) 
SELECT 'some_string'
WHERE NOT EXISTS(SELECT 1 FROM table WHERE unique_name = 'some_string')
Run Code Online (Sandbox Code Playgroud)

你也可以

INSERT INTO table (unique_name)
VALUES('some_string')
ON CONFLICT (unique_name) DO NOTHING
Run Code Online (Sandbox Code Playgroud)

但是,如果您需要在单个查询中插入或更新,那么以下示例适用于您:

INSERT INTO distributors (did, dname)
VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc')
ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname;
Run Code Online (Sandbox Code Playgroud)

这是PostgreSQL文档中的一个示例。

  • 我问了这个问题,但是我仍然不理解它在sqlalchemy中是如何工作的。 (3认同)