条件 table 更新

Conditional table updates

考虑以下 table。

myTable
+----+-----------+------------------------------------+
| Id | responseA |             responseB              |
+----+-----------+------------------------------------+
|  1 |           | {"foo":"bar","lvl2":{"key":"val"}} |
+----+-----------+------------------------------------+

其中:

Id, INT (11) PRIMARY
responseA, TEXT utf8_unicode_ci
responseB, TEXT utf8_unicode_ci

假设我想有条件地用一些外部数据更新table。条件是:

• 如果 responseA 中没有任何内容,则用外部数据填充它,否则

• 如果 responseA 中的某些内容,请保持原样,并填充 responseB与外部数据

我非常确信我可以通过这样做来获得我想要的东西:

UPDATE myTable
SET
    responseA = IF(TRIM(responseA) = '','foo',TRIM(responseA)),
    responseB = IF(TRIM(responseA) != '','foo',TRIM(responseB))
WHERE Id = 1

但是,这会将 responseAresponseB 更新为相同的值 - foo,从而使 table:

myTable
+----+-----------+-----------+
| Id | responseA | responseB |
+----+-----------+-----------+
|  1 |    foo    |    foo    |
+----+-----------+-----------+

我希望我的 table 在更新后看起来像这样:

myTable
+----+-----------+------------------------------------+
| Id | responseA |             responseB              |
+----+-----------+------------------------------------+
|  1 |    foo    | {"foo":"bar","lvl2":{"key":"val"}} |
+----+-----------+------------------------------------+

我误解了什么,我怎样才能实现这个条件更新?更新是按顺序发生的吗?如果是这样,我想这可以解释为什么这两个字段都被更新了。

UPDATE TABLE
SET responseA = CASE WHEN responseA IS NULL
                     THEN @data
                     ELSE responseA
                     END,
    responseB = CASE WHEN responseA IS NULL
                     THEN responseB 
                     ELSE @data
                     END
;
    

responseA 的值似乎在评估 responseB 的 IF() 之前发生了变化。

一个可能的解决方案是进行简单的更新:

UPDATE mytable SET responseA = ? WHERE id = 1

然后调整触发器中的列,您可以在其中访问列的原始值和新值:

CREATE TRIGGER t BEFORE UPDATE ON mytable
FOR EACH ROW BEGIN
  IF TRIM(OLD.responseA) != '' THEN
    SET NEW.responseB = NEW.responseA;
    SET NEW.responseA = OLD.responseA;
  END IF;
END

(我没有测试过这个。)

我还假设您对 ''(空字符串)而不是 NULL 的测试是故意的,并且您知道 NULL 与 ''.

不同

UPDATE 语句中的关键点是您应该首先更新列 responseB,以便列 responseA 保留其原始值,您可以在尝试时再次检查更新它:

UPDATE myTable
SET responseB = CASE WHEN TRIM(responseA) = '' THEN responseB ELSE 'foo' END,
    responseA = CASE WHEN TRIM(responseA) = '' THEN 'foo' ELSE responseA END
WHERE Id = 1;

此处是您更改后的查询

UPDATE myTable
SET
    responseB = IF(TRIM(responseA) != '','foo',TRIM(responseB)),
    responseA = IF(TRIM(responseA) = '','foo',TRIM(responseA))
WHERE Id = 1