正确的SQLite语法-使用存在的位置更新SELECT

正确的SQLite语法-使用存在的位置更新SELECT,sqlite,sql-update,where,exists,Sqlite,Sql Update,Where,Exists,我正在尝试更新SQLite表中列中的选定值。我只想更新maintable中满足条件的单元格,并且这些单元格必须更新为从子表中获取的单个值 UPDATE maintable SET value=(SELECT subtable.value FROM maintable, subtable WHERE maintable.key1=subtable.key1 AND maintable.key2=subtable.key2) WHERE EXISTS (SELECT subtable.value

我正在尝试更新SQLite表中列中的选定值。我只想更新maintable中满足条件的单元格,并且这些单元格必须更新为从子表中获取的单个值

UPDATE maintable
SET value=(SELECT subtable.value FROM maintable, subtable
WHERE  maintable.key1=subtable.key1 AND maintable.key2=subtable.key2)
WHERE EXISTS (SELECT subtable.value FROM maintable, subtable
WHERE  maintable.key1=subtable.key1 AND maintable.key2=subtable.key2)
我尝试了以下语法,但只得到一个单元格更新。我还尝试过将所有单元格更新为子表的第一个选定值的替代方案

UPDATE maintable
SET value=(SELECT subtable.value FROM maintable, subtable
WHERE  maintable.key1=subtable.key1 AND maintable.key2=subtable.key2)
WHERE EXISTS (SELECT subtable.value FROM maintable, subtable
WHERE  maintable.key1=subtable.key1 AND maintable.key2=subtable.key2)

什么是合适的语法?

您需要使用INSERT或REPLACE语句,类似于以下内容:

假设maintable有4列:key、col2、col3、col4 您希望使用子表中的匹配值更新col3

INSERT OR REPLACE INTO maintable
SELECT maintable.key, maintable.col2, subtable.value, maintable.col4
FROM maintable 
JOIN subtable ON subtable.key = maintable.key
您可以通过更新选择来执行此操作,但一次只能执行一个字段。如果Sqlite支持update语句上的连接就好了,但它不支持

这里有一个相关的SO问题,但针对SQL Server。这里也有类似的答案

sqlite> create table t1 (id int, value1 int);
sqlite> insert into t1 values (1,0),(2,0);
sqlite> select * from t1;
1|0
2|0
sqlite> create table t2 (id int, value2 int);
sqlite> insert into t2 values (1,101),(2,102);
sqlite> update t1 set value1 = (select value2 from t2 where t2.id = t1.id) where t1.value1 = 0;
sqlite> select * from t1;
1|101
2|102

在这种情况下,对于maintable中的每个raw,它只更新子表中的一个值。 错误是子表包含在SELECT语句中

更新主表 设置值=选择子表.value 从子表 其中maintable.key1=subtable.key1; 我们可以使用with子句+列名列表+select stmt from来生成如下内容:

CREATE TABLE aa (
_id INTEGER PRIMARY KEY,
a1 INTEGER,
a2 INTEGER);

INSERT INTO aa  VALUES (1,10,20);
INSERT INTO aa  VALUES (2,-10,-20);
INSERT INTO aa  VALUES (3,0,0);

--a bit unpleasant because we have to select manually each column and it's just a lot to write
WITH bb (_id,b1, b2)  
AS  (SELECT _id,a1+2, a2+1 FROM aa WHERE _id<=2) 
UPDATE aa  SET a1=(SELECT b1 FROM bb WHERE bb._id=aa._id),a2=(SELECT b2 FROM bb WHERE bb._id=aa._id)
WHERE _id in (SELECT _id from bb);

--soo now it should be (1,10,20)->(1,12,21) and (2,-10,-20)->(2,-8,-19), and it is
SELECT * FROM aa;


--even better with one select for each row!
WITH bb (_id,b1, b2)  
AS  (SELECT _id,a1+2, a2+1 from aa WHERE _id<=2)
UPDATE aa  SET (a1,a2)=(SELECT b1,b2 FROM bb WHERE bb._id=aa._id)
WHERE _id in (SELECT _id from bb);

--soo now it should be (1,12,21)->(1,14,22) and (2,-8,-19)->(2,-6,-18), and it is
SELECT * FROM aa;


--you can skip the WITH altogether
UPDATE aa SET (a1,a2)=(SELECT bb.a1+2, bb.a2+1 FROM aa AS bb WHERE aa._id=bb._id)
WHERE _id<=2;
--WHERE _id IN (SELECT bb._id FROM aa AS bb WHERE _id<=2)

--soo now it should be (1,14,22)->(1,16,23) and (2,-6,-18)->(2,-4,-17), and it is
SELECT * FROM aa;

希望sqlite足够智能,不会以增量方式进行查询,但根据文档,它是这样的。当使用一个select案例2和3设置多个列时,无效id将给出一个不能忽略的错误。使用ON IGNORE,案例1将列设置为null,这也是不好的。

回答正确,但您不需要执行INSERT或REPLACE操作。我找到了另一个答案:插入或替换也需要主键的所有字段都正确吗?@Jess答案在哪里?@cikatomo抱歉,我不明白。我以前从来没有使用过INSERT或REPLACE。情况1是有一个大的查询对集合行执行直接的、大量无意识的不做任何特殊查询。情景2既别致又漂亮。场景3简短而漂亮。对于android用户,请注意场景2和场景3仅适用于android 8.0 API 26,而sqllite的版本是v3.15