简体   繁体   English

Python peewee,使用EXCLUDED解决冲突解决

[英]Python peewee, using EXCLUDED to resolve conflict resolution

I am trying to upsert a record, using the syntax shown here .我正在尝试使用此处显示的语法插入一条记录。

from peewee import EXCLUDED
query = (MyTable.insert(
    id=sched.id,
    idenc=sched.idenc,
    createdon=sched.createdon,
    modifiedon=sched.modifiedon,
    deletedon=sched.deletedon,
    canceledon=sched.canceledon,
    is_deleted=sched.is_deleted,
    start_date=sched.start_date,
    end_date=sched.end_date,
    label=sched.label
)
    .on_conflict(conflict_target=[MyTable.id,
                                  MyTable.start_date,
                                  MyTable.end_date],
                 update={
                     MyTable.modifiedon: EXCLUDED.modifiedon,
                     MyTable.label: EXCLUDED.label
    },
    where=(EXCLUDED.modifiedon > MyTable.modifiedon)))
query.execute()

The idea is to update the entry if it is the latest, where modifiedon is a varchar field holding a timestamp, for example: 2022-11-22T17:00:34.965Z这个想法是更新条目,如果它是最新的,其中modifiedon是一个包含时间戳的varchar字段,例如: 2022-11-22T17:00:34.965Z

This creates sql statement as shown below,这将创建如下所示的 sql 语句,

(
    'INSERT INTO "mytable" ("id", "idenc", "createdon", "modifiedon", "deletedon", "canceledon", "isdeleted", "startdate", "enddate", "label") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT ("id", "startdate", "enddate") DO UPDATE SET "modifiedon" = EXCLUDED."modifiedon", "label" = EXCLUDED."label" WHERE
     (EXCLUDED."modifiedon" > "mytable"."modifiedon")',
    [ 'ymmqzHviWsMgabzPTEKU',
    'ebbe37ec-cb75-5bc6-9466-b170a458c469',
    '2022-11-22T17:00:05.175Z',
    '2022-12-05T11:23:31.563569Z',
    '',
    'None',
    False,
    '2022-11-21T18:01:00.000Z',
    '2022-12-31T17:59:00.000Z',
    '1' ]
)

But this does nothing and no exception is thrown either.但这什么都不做,也不会抛出异常。 Running the query straight on MySQL raises syntax error.直接在 MySQL 上运行查询会引发语法错误。

Any idea?任何的想法?

[EDIT] [编辑]

To add more to the context, how do I upsert a row, with a where condition.要向上下文添加更多内容,我如何使用 where 条件插入一行。 Here, the primary key is composite(id,start_date, end_date) , So when an entry with more recent modifiedon is already in the db, how do I make sure that I am not overwriting the latest one?在这里,主键是composite(id,start_date, end_date) ,所以当数据库中已经有modifiedon的条目时,我如何确保我没有覆盖最新的条目?

Theoretically speaking, an INSERT/REPLACE with a WHERE clause on a non primary key.从理论上讲,在非主键上带有WHERE子句的INSERT/REPLACE Is that possible with peewee? peewee可以吗?

Currently what I'm doing is,目前我正在做的是,

item_existing, created = MyTable.get_or_create()
if not created:
 if item_existing.modifiedon < item.modifiedon:
   Mytable.replace()

But this is prone to race condition.但这很容易出现竞争条件。 Any other good way to solve this?还有什么好的方法可以解决这个问题吗?

PS: DB Engine: 5.7.mysql_aurora.2.08.3 PS:数据库引擎:5.7.mysql_aurora.2.08.3

MySQL does not not support the specification of conflict targets, nor does it support EXCLUDED, nor does it support a WHERE clause. MySQL 不支持指定冲突目标,也不支持EXCLUDED,也不支持WHERE子句。 It also depends, somewhat, on whether you're using MySQL or MariaDB as they each are slightly different, but the jist is that you have limited options and can only choose to update certain values.这在某种程度上也取决于您使用的是 MySQL 还是 MariaDB,因为它们略有不同,但关键是您的选择有限,只能选择更新某些值。

Attempting to use those APIs should be raising an exception, so perhaps you are on an older version of Peewee.尝试使用这些 API 应该引发异常,因此您可能使用的是旧版本的 Peewee。

Basically with MySQL you can choose to preserve data that would be inserted (eg, overwrite the existing data with the data for the columns listed in preserve), or you can update certain columns with entirely different values.基本上,对于 MySQL,您可以选择保留将要插入的数据(例如,用保留中列出的列的数据覆盖现有数据),或者您可以使用完全不同的值更新某些列。

Example of inserting a row and, if it already exists, just applying a change to it's "modified":插入一行的示例,如果它已经存在,则只需对其“修改”应用更改:

(Table
 .insert({'created': now(), 'modified': now(), 'name': 'Something'})
 .on_conflict(preserve=[Table.modified])
 .execute())

Example of inserting a row and, if it already exists, setting its "modified" to something entirely different:插入一行的示例,如果它已经存在,则将其“修改”设置为完全不同的内容:

(Table
 .insert({'created': now(), 'modified': now(), 'name': 'Something'})
 .on_conflict(update={Table.modified: something_totally_different()})
 .execute())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM