【问题标题】:MySQL - INSERT INTO … ON DUPLICATE KEY UPDATE with values select from the same tableMySQL - INSERT INTO ... ON DUPLICATE KEY UPDATE 与从同一个表中选择的值
【发布时间】:2024-01-19 09:24:01
【问题描述】:

我有两张表,一张是posts(ID, edited_date, is_public, ... etc),一张是post_pagination(index, post_id),用于存放帖子的分页数据。在post_pagination 中,index 是主键。

分页过程中的一个步骤,我需要检查排序结果和post_pagination表,并进行INSERT/UPDATE,例如:

INSERT INTO post_pagination(`index`, post_id)
SELECT * /* full outer join new sorted result and pagination table */
FROM (
    WITH 
    cte1 AS (
        SELECT ROW_NUMBER() OVER(ORDER BY edited_date DESC, ID DESC) AS new_rank, ID
        FROM posts
        WHERE is_public = 1
    ),
    cte2 AS (
        SELECT `index`
        FROM post_pagination
    )
    SELECT `index` AS dummy_rank, ID
    FROM cte2
    LEFT JOIN cte1 on `index` = new_rank
    UNION ALL
    SELECT new_rank AS dummy_rank, ID
    FROM cte2
    RIGHT JOIN cte1 on `index` = new_rank
    WHERE `index` IS NULL
) AS a
ORDER BY dummy_rank
ON DUPLICATE KEY UPDATE post_id = ID

第一次运行这个查询,post_pagination为空,所以MySQL将所有数据插入到表中。

index  post_id
1      390
2      391
3      392
4      393
5      307

效果很好。

当我第二次运行时,我希望所有数据都不会改变,但它会将所有 post_id 字段更新为结果的最后一个值。

index  post_id
1      307
2      307
3      307
4      307
5      307

我做了一些测试,似乎使用从同一个表中选择的值将值插入到表中会导致这个问题,但我不知道为什么

现在我只需将查询的最后一行修改为:

ON DUPLICATE KEY UPDATE post_id = ID + 0

有没有更好的方法来解决这个问题?

【问题讨论】:

    标签: mysql insert on-duplicate-key


    【解决方案1】:

    你能改用临时表吗?

    CREATE TEMPORARY TABLE `post_pagination_temp` (
     `index` INTEGER(1) AUTO_INCREMENT PRIMARY KEY,
     `post_id` INTEGER(1)
    );
    
    INSERT INTO `post_pagination_temp` (`post_id`)
    SELECT `ID` FROM `posts` ORDER BY `edited_date` DESC, `ID` DESC;
    
    INSERT INTO `post_pagination`
    SELECT * FROM `post_pagination_temp`
    ON DUPLICATE KEY UPDATE `index` = VALUES(`index`);
    

    这假设您在 post_pagination 上具有正确的索引,即唯一的唯一性是 post_id 上的主键。

    【讨论】:

      最近更新 更多