SQLite内部联接 - 使用另一个表中的值进行更新

nav*_*eet 13 sql sqlite join sql-update

这很容易,已被多次询问,但我无法让它工作.我认为应该工作的SQL查询是:

    UPDATE table2
       SET dst.a = dst.a + src.a,
           dst.b = dst.b + src.b,
           dst.c = dst.c + src.c,
           dst.d = dst.d + src.d,
           dst.e = dst.e + src.e
      FROM table2 AS dst 
INNER JOIN table1 AS src
        ON dst.f = src.f
Run Code Online (Sandbox Code Playgroud)

Ton*_*bbs 25

使用update语句是不可能的,因为不支持更新语句中的sqlite连接.请参阅docs: update语句

如果您只想将单个列更新为静态值,则可以在update语句中正确使用子查询.请参阅此示例:如何在SQLite上连接表时进行更新?

现在在您的示例中,假设"列f"上有唯一键 - 我提出的解决方法/解决方案是使用replace语句:

replace into table2
(a, b, c, d, e, f, g)
select src.a, src.b, src.c, src.d, src.e, dest.f, dest.g
from table1 src
inner join table2 dest on src.f = dest.f
Run Code Online (Sandbox Code Playgroud)

我还在table2"column g"中添加了一个额外的列,以显示如何使用此方法"更新"某些列.

另一件要谨慎的事情是,如果你使用"PRAGMA foreign_keys = ON;" 因为行被有效删除和插入,所以可能会出现问题.


Tri*_*und 5

我想出了一种使用TRIGGER的替代技术并"反转"更新的方向,尽管以源表中的虚拟字段为代价.

一般而言,您有一张Master桌子和一张Updates桌子.您希望MasterUpdates关键字段链接的相应字段更新记录的部分/全部字段Key.

而不是UPDATE Master SET ... FROM Master INNER JOIN Updates ON Mater.Key = Updates.Key你做以下事情:

  1. TriggerFieldUpdates表中添加虚拟字段以充当触发器的焦点.

  2. 在此字段上创建触发器:

    CREATE TRIGGER UpdateTrigger AFTER UPDATE OF TriggerField ON Updates
    BEGIN
        UPDATE Master SET
            Field1 = OLD.Field1,
            Field2 = OLD.Field2,
            ...
        WHERE Master.Key = OLD.Key
    END;
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用以下命令启动更新过程:

    UPDATE Updates SET TriggerField = NULL ;
    
    Run Code Online (Sandbox Code Playgroud)

笔记

  1. 虚拟字段仅仅是触发器的锚点,因此任何其他字段UPDATE Updates SET ...都不会触发更新Master.如果你只是INSERT进入Updates那时你不需要它(并且可以OF TriggerField在创建触发器时删除该子句).

  2. 从一些粗略和准备好的时间,这似乎与大致相同的速度,REPLACE INTO但避免了删除和添加行的感觉 - 稍微错误的技术.如果您只更新几个字段,那么它也更简单,Master因为您只列出要更改的字段.

  3. 它比我见过的其他替代方案快了几个数量级UPDATE ... FROM:

    UPDATE Master SET
        Field1 = ( SELECT Field1 FROM Updates WHERE Mater.Key = Updates.Key ),
        Field1 = ( SELECT Field1 FROM Updates WHERE Mater.Key = Updates.Key ),
        ...
    ;
    
    Run Code Online (Sandbox Code Playgroud)

    对于Tony和我的方法,在1700条记录中更新六个字段大约是0.05s,但是对于该方法来说是2.50sUPDATE ... ( SELECT... ).

  4. AFTER UPDATE触发器Master似乎按预期触发.