JSON相当于INSERT ... ON DUPLICATE KEY UPDATE,并且增加当前存在的值

问题描述 投票:0回答:1

我有这样的情况,简化:

CREATE TABLE `user_points` (
  `date` date NOT NULL,
  `user_id` mediumint(8) unsigned NOT NULL,
  `points` int(11) NOT NULL,
  PRIMARY KEY (`date`, `user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

所以,如果今天用户获得积分,我会:

INSERT INTO user_points (date, user_id, points) VALUES (CURDATE(),?,1) 
ON DUPLICATE KEY UPDATE points=points+1;

现在,想象一下我想将这些点存储到一个JSON字段中,它不仅包含点,而且可能包含其他属性(这些属性是动态的,有些客户端永远不会使用任何属性,其他客户端会使用很多属性,这就是我喜欢的原因) JSON)

因此,我想在points列上设置$.points,而不是添加到data

是否可以进行单个查询来执行此操作?

  • 如果没有包含此类日期和user_id的行,请插入一个包含data = {"points": 1}的新行
  • 如果有一行且数据为null,则为SET data="{"points": 1}"
  • 如果有一行有一些json,但不是$ .data,JSON_SET(data, '$.points', 1)
  • 如果有一行和一些$ .points,则将点数增加一。

我试过了:

SELECT JSON_SET('{"a": 1, "l": 2}', '$.points', 
    JSON_EXTRACT('{"a": 1, "l": 2}', '$.points')+1) AS 'Data';

但它不起作用(因为NULL + 1 = NULL而不是1)

编辑:可以用COALESCE解决,但我不确定它是最好的解决方案:

SELECT JSON_SET('{"a": 1, "l": 2}', '$.points', 
    COALESCE(JSON_EXTRACT('{"a": 1, "l": 2}', '$.points'), 0)+1) AS 'Data';

完整的查询将是:

INSERT INTO user_points (date, user_id, data) VALUES (CURDATE(),?,'{"points":1}') 
    ON DUPLICATE KEY UPDATE data=JSON_SET(data, '$.points', 
    COALESCE(JSON_EXTRACT(data, '$.points'), 0)+1);
mysql
1个回答
1
投票

这是我到目前为止找到的工作解决方案,它需要两次COALESCE(如果data为null,以防data.points为null:

INSERT INTO user_data (date, user_id, data) VALUES (CURDATE(), ?, '{"points":1}')
    ON DUPLICATE KEY UPDATE data=JSON_SET(COALESCE(data, '{}'), '$.points', 
    COALESCE(JSON_EXTRACT(data, '$.points'), 0)+1);

我想知道为什么它增加了一个.0 ..

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.