插入if不存在-在python+sqlalchemy中

6gpjuf90  于 12个月前  发布在  Python
关注(0)|答案(2)|浏览(89)

问题是:找到一个独立于rdbms的方法来使用sqlalchemy从数据库中获取具有指定键的值!如果键不存在,则生成一个新值并将其插入到表中。在多用户+多进程环境中...
我有两个想法:第一次得到它,如果它返回None,然后生成一个新的和插入,如果它是不成功的(因为重复的关键字),然后再得到它。
第二步:锁定表,获取它,如果返回None,则生成一个新的并插入
第二个似乎更好,但我找不到一个独立于RDBMS的锁定表的解决方案。(session.execute('lock...')是不合适的,因为它直接使用SQL)
第一个看起来.

de90aj5v

de90aj5v1#

不幸的是,我不确定合并的性能如何,但对于this post(我强烈推荐),最好的选择是使用upsert,然后从表中读取

from sqlalchemy.dialects.postgresql import insert

insert_stmt = insert(my_table).values(id='id',data='data')
do_nothing_stmt = insert_stmt.on_conflict_do_nothing(index_elements=['id'])
db.query(table).get("id")

字符串

jjhzyzn0

jjhzyzn02#

一次调用就可以完成。这并不容易,因为insert.values(**items)不允许where子句与NOT EXISTS组合。我们需要一个子查询,但是我们也需要每列的文字和插入的键。同时datetime的文字引起了插入问题(格式化,也许只是postgres)。我想知道是否有更好的方法来解决日期问题。
在下面的例子中,item_dict是一个带有field:value条目的字典。它只在invoice_number和invoice_line_number不存在的情况下插入。

# Create literals for select. Datetime conversion was needed because insert failed without it due to formatting issues.
    literals = [literal(val) if key != 'invoice_date' else literal(val.strftime("%Y-%m-%d")) for key,val in item_dict.items() ]
    
    # NOT exists subquery providing the literals.
    insert_select = select(literals).where(
        ~exists(literal(1)).where(
            (performance_row_table.c.invoice_number == item_dict['invoice_number']) &
            (performance_row_table.c.invoice_line_number == item_dict['invoice_line_number'])
        )
    )

    keys = [key for key in item_dict.keys()]
    # Insert using the subquery
    insert_statement = performance_row_table.insert().from_select(keys, insert_select).returning(performance_row_table)

    compiled = insert_statement.compile(compile_kwargs={"literal_binds": True})
    print(compiled)
    insert_result = session.execute(insert_statement).fetchone()

字符串

相关问题