mysql UPDATE语句逐个更新列?

mysql UPDATE语句逐个更新列?,mysql,sql,sql-update,mysql-8.0,Mysql,Sql,Sql Update,Mysql 8.0,我在mysql 8中编写了一个查询,在插入的重复键上,因为有一个唯一的索引,所以它只在特定条件下更新受影响的行。我的条件是列上的start\u值是否已更改。所以我写了这个查询 INSERT INTO timers ( started_on, end_on, message, first_alert_before_end_time, alerts_interval,

我在mysql 8中编写了一个查询,在插入的重复键上,因为有一个唯一的索引,所以它只在特定条件下更新受影响的行。我的条件是列上的
start\u值是否已更改。所以我写了这个查询

INSERT INTO timers (
            started_on,
            end_on,
            message,
            first_alert_before_end_time,
            alerts_interval,
            referred_flow_instance_id,
            referred_page_id,
            referred_json_timer_id,
            started_by_user_id
        ) VALUES (
            '2025-01-06',
            DATE_ADD('2025-01-06', INTERVAL 5184000 SECOND),
            'Sta scadendo il fascicolo',
            2592000,
            86400,
            1413,
            14,
            1,
            79
        )
        ON DUPLICATE KEY 
        UPDATE
            started_on = IF( DATE(started_on) = DATE('2025-01-01'), started_on, '2025-01-06'),
            end_on = IF( DATE(started_on) = DATE('2025-01-01'), end_on,  DATE_ADD('2025-01-06', INTERVAL 5184000 SECOND)),
            started_by_user_id = IF( DATE(started_on) = DATE('2025-01-01'), started_by_user_id, 79),
            deleted_by_user_id = IF( DATE(started_on) = DATE('2025-01-01'), deleted_by_user_id, NULL),
            reminded_later_by_user_id = IF( DATE(started_on) = DATE('2025-01-01'), reminded_later_by_user_id, NULL),
            deleted = IF( DATE(started_on) = DATE('2025-01-01'), deleted, 0)
    ;
我不分析有效的插入,只分析重复关键部件的更新。

我注意到一个意外的结果:当更新中的IF条件为true时,只更新了started_on,而没有更新具有相同条件的其他列

因此,我的直觉是,我的更新查询的第一行(
started\u on=IF(DATE(started\u on)=DATE('2025-01-01')、started\u on,'2025-01-06'
)突然更新了started\u on列,因此由于值发生了更改,以下条件会导致false。 我试着把更新开始的部分放在更新中所有列的末尾,现在它们都被更新了

我想确定并确认我的直觉是否正确,但在网上搜索了一下后,我什么也没找到


编辑:似乎运行通过mysql workbench从顶部开始更新的查询即使在顶部也可以运行,但我需要使用xdevapi库在节点中运行它,并且只有在放在底部时才可以运行。

您的直觉是正确的。
中记录了此行为,并举例说明:

下面语句中的第二个赋值将col2设置为 当前(已更新)col1值,不是原始的col1值。结果 col1和col2具有相同的值。此行为与 标准SQL

UPDATE t1 SET col1 = col1 + 1, col2 = col1;
单表更新分配通常从左到右进行评估 右侧


在mysql 5.6和所有版本的MariaDB中,对列的任何引用都将获得该列的原始值

对于mysql 5.7和mysql 8.0,更为复杂:

在单个表更新中,更新实际上是从左到右进行的,每个列更新都会获得列的值,就好像前面的所有更新都已应用一样

在多表更新中,对主表的任何更新似乎都是从左到右首先发生的,就像在单个表更新中一样。但是对联接表中的列的更新似乎总是在主表更新完成时获得任何值,因此对主表列的任何更改都将生效,即使这些主表列仅在语句的后面设置,对于对联接表列的引用,使用原始值,即使在语句的前面更改了这些联接表列