在 SQLite 中使用 Join 进行更新

Update with Join in SQLite

提问人:Carter 提问时间:10/9/2013 最后编辑:ArulkumarCarter 更新时间:8/16/2023 访问量:90311

问:

我有 2 个表,并希望用另一个表的值更新其中一个表。

software
---------
id ,
purchprice

softwarecost
------------
id ,
purchprice

我已经尝试了这些查询,但是,SQLite不支持带有UPDATE.JOINS的任何人,任何人都可以提出查询,感谢您的帮助。

UPDATE software 
SET software.purchprice=softwarecost.purchprice 
WHERE software.id=softwarecost.id

UPDATE software 
INNER JOIN softwarecost on software.id=softwarecost.id 
SET software.purchprice=softwarecost.purchprice 
SQLite的

评论

1赞 juergen d 10/9/2013
当然,sqlite支持连接。
0赞 Ciro Santilli OurBigBook.com 11/4/2021
与 DELETE 相关:stackoverflow.com/questions/24511153/...

答:

-3赞 Bogdan Burym 10/9/2013 #1

这里没有 JOIN:

UPDATE software
SET software.purchprice=softwarecost.purchprice
WHERE software.id=softwarecost.id

这是行不通的:

UPDATE software s INNER JOIN softwarecost sc on s.id=sc.id
SET s.purchprice=sc.purchprice 

SQLite确实不支持UPDATE查询中的JOIN http://sqlite.org/lang_update.html

使用REPLACE怎么样?
也许你可以:

REPLACE INTO software
SELECT id, purchprice
FROM softwarecost

评论

0赞 Carter 10/9/2013
嗨,波格丹,谢谢你的回复,我收到这个错误。SQLiteManager:可能的 SQL 语法错误:UPDATE software s INNER JOIN softwarecost sc on s.id=sc.id SET s.purchprice=sc.purchprice [ near “s”: 语法错误 ] 异常名称: NS_ERROR_FAILURE
48赞 CL. 10/9/2013 #2

您必须使用相关的子查询查找相应的值:

UPDATE software
SET purchprice = (SELECT purchprice
                  FROM softwarecost
                  WHERE id = software.id)

评论

7赞 Colin 't Hart 10/9/2013
但请注意,这将设置为在 中找不到“相关”行的位置。software.purchpricenullsoftwarecost
4赞 Ari B. Friedman 11/14/2013
@Colin哈特:这似乎是理想的行为,不是吗?
10赞 mcfly soft 8/7/2014
我刚刚试过这个。整个表软件中的字段 PurchPrice 将具有相同的值。它不执行联接。
0赞 lmrta 6/19/2017
SQLite3 似乎不支持引用数据库中其他表的语句(我正在运行与上面类似的代码并收到错误)。有任何线索,或者我应该提出一个新问题吗?WHEREError: no such column: software.id
0赞 CL. 6/19/2017
@lmrta 您只能引用 UPDATE 或 SELECT 使用的表。
1赞 Reginaldo Marcilon 1/9/2014 #3

Carter,>>near “s”: syntax error<<的问题与ALIAS的使用有关。UPDATE 命令不接受 ALIAS。如果你尝试关于REPLACE的bogdan提示,你可以加入到SELECT子句中。

98赞 Durai Amuthan.H 1/12/2014 #4

这将起作用

UPDATE 
      software
SET purchprice = (SELECT purchprice
                  FROM softwarecost
                  WHERE id = software.id) 
where EXISTS (SELECT purchprice
                  FROM softwarecost
                  WHERE id = software.id)

这里我们使用 exist,因为 否则,如果未找到“相关”行,则查询会将 Software.PurchPrice 设置为 null。

评论

17赞 Pelle Jacobs 11/19/2020
从 v3.33(2020 年 8 月 14 日发布)开始,sqlite 支持 UPDATE FROM 语法: sqlite.org/lang_update.html#upfrom
12赞 Vasilii P 3/16/2015 #5

这个声明会很好用!

它只会更新“software”中在“softwarecost”中具有相同 ID 的行!

UPDATE software SET software.purchprice = 
     (SELECT purchprice FROM softwerecost WHERE software.id = softwerecost.id) 
     WHERE id IN (SELECT id FROM softwarecost);

还有一种方法:

DELETE FROM software WHERE id IN (SELECT id FROM softwarecost);
INSERT INTO software SELECT * FROM softwarecost;

...如果您必须更新所有列(如果您有更多列要更新),这种方式会更方便

-2赞 user11970466 8/24/2019 #6

您可以尝试给定的,

UPDATE software SET purchprice = (SELECT purchprice FROM softwarecost a WHERE a.id =software.id) where purchprice IN(SELECT distinct(purchprice) FROM softwarecost a WHERE a.id = software.id)
4赞 Vic Fanberg 11/20/2019 #7

我知道这很旧,但我更喜欢

UPDATE software
SET purchprice = IFNULL( (SELECT purchprice
                          FROM softwarecost
                          WHERE id = software.id), purchprice) 

它可以作为UPDATE with JOINs问题的一般解决方案,并节省SQLite必须执行第二个SELECT语句来验证子查询中是否确实有一行。

评论

0赞 Julen 2/12/2020
此解决方案较短,不会重复查询。但是,我测试了两者,由于某种原因,这个比带有“WHERE EXISTS”的慢几个数量级。因此,只有在速度无关紧要的情况下才使用。
0赞 Vic Fanberg 2/12/2020
如果 NULL 在列 purchprice 中很少见并且表非常大,这实际上是有道理的,因为 SQL 在不需要的时候必须对值进行大量搜索。因此,这取决于您的数据集,即您预计的主要是 NULL 还是大部分已填充的值。如果您大部分已经填写了值并且表很大,那么使用此格式 SQL 就会受到打击。如果表很小,或者 purchprice 列中大部分为 NULL,或者可维护性是 SQL 语句的主要关注点,则使用此格式 SQL。
0赞 Vic Fanberg 2/13/2020
我将对此再补充一点意见。在实践中,通常有一些其他条件来减少 update 语句将查看的值集,例如今天创建的所有记录或将在 update 语句本身的 where 子句中指定的特定批号,以减少 update 语句将查看的行数。然后,它可以与 WHERE EXISTS 版本一样高效,但更易于维护。
6赞 Eric Woltermann 2/29/2020 #8

我刚刚找到了这个,使用UPSERT

INSERT INTO software (id, purchprice)
SELECT a.id, b.purchprice FROM software AS a INNER JOIN softwarecost AS b ON a.id=b.id
ON CONFLICT(id) DO UPDATE SET purchprice=excluded.purchprice

这仅在您有以下情况时有效

  • SQLite 版本 3.24.0 或更高版本,以及
  • 对 software.id 的唯一约束,例如将其定义为主键。

它不需要可能缓慢的相关子查询,并且可以处理多个列更新。

评论

0赞 WillD 6/14/2020
你从哪里被“排除”?
1赞 Eric Woltermann 6/18/2020
它是一个保留的伪表,由 UPSERT 语法自动提供。请参阅链接的SQLite文档:“DO UPDATE表达式中的列名是指在尝试INSERT之前列的原始未更改值。若要使用约束未失败时本应插入的值,请将特殊的“excluded.”表限定符添加到列名中。
0赞 Alexandr Zarubkin 11/6/2023
谢谢。它对我来说可以替代 SQLite 3.27.2 上的 UPDATE FROM(因为 UPDATE FROM 仅在 3.33 之后可用)。
5赞 turc1656 2/27/2021 #9

这里的其他答案大多是正确的,但需要稍作更改。至少我当然需要做出改变才能让它发挥作用。不确定这是多年来对SQLite的更改,还是只是它从未在这里被发现,但是您需要从子句中完全限定对列的引用,而不仅仅是.如果不这样做,我刚刚运行的查询使所有条目都具有相同的值,并且它是链接的第一个值 - 这意味着 的所有条目都变得与 中的第一个条目相同。我认为,这是由于 id 列是模棱两可的,如果它只是“id=software.id”,因此它本身就有链接。idsoftwarecostWHEREWHERE softwarecost.id = software.idWHERE id = software.idsoftware.purchpricesoftwarecost.purchprice

UPDATE 
      software
SET purchprice = (SELECT purchprice
                  FROM softwarecost
                  WHERE softwarecost.id = software.id) 
where EXISTS (SELECT purchprice
                  FROM softwarecost
                  WHERE softwarecost.id = software.id)
0赞 kader hussain 10/16/2021 #10
Update software 
  set Column1 = anyValue
  where id in (Select sf.id from software sf join softwarecost  sfc on sf.id=sfc.id
    where sfc.purchprice='anyValue' 
  )

如果您要更新的内容与 Join 和 Where 条件

19赞 Jan Derk 11/4/2021 #11

使用 v3.33(2020 年 8 月 14 日发布)中引入的新 UPDATE FROM 语法,正如 Pelle Jacobs 在评论中建议的那样。

UPDATE software
SET purchprice = c.purchprice
FROM (SELECT purchprice, id FROM softwarecost) AS c
WHERE c.id = software.id;

评论

1赞 Gad D Lord 12/29/2022
请注意,从 3.33 版开始支持“update from”