sqlite 为什么此选择查询可以提供所需的结果,但在修改为更新时却不能?

5hcedyr0  于 2022-12-13  发布在  SQLite
关注(0)|答案(1)|浏览(151)

我正在尝试更新一个表,以纠正加载到SQLite中的数据中的错误。这是一个问题的示例。
在安排要加载的数据时跳过了一段代码,这样,从indexInter = 4开始,“code”列与每行中的其余数据有一行不同步(落后)。但是,当该查询被修改为更新时,所有行都被更新为第一个匹配行。
你能告诉我我犯了什么新手错误吗?我忽略了什么基本原则?谢谢。

sqlite> .dump testUpdate
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE testUpdate (indexRow integer unique, indexInter integer, code text);
INSERT INTO testUpdate VALUES(130120390150,1,'H1961');
INSERT INTO testUpdate VALUES(130120390250,2,'H8033');
INSERT INTO testUpdate VALUES(130120390350,3,'H1732');
INSERT INTO testUpdate VALUES(130120390450,4,'H3117');
INSERT INTO testUpdate VALUES(130120390470,NULL,'punct3');
INSERT INTO testUpdate VALUES(130120390550,5,'H7969');
INSERT INTO testUpdate VALUES(130120390650,6,'H398');
INSERT INTO testUpdate VALUES(130120390750,7,'H8354');
INSERT INTO testUpdate VALUES(130120390770,NULL,'punct2');
INSERT INTO testUpdate VALUES(130120390850,8,'');
INSERT INTO testUpdate VALUES(130120390950,9,'H3559');
INSERT INTO testUpdate VALUES(130120391050,10,'');
INSERT INTO testUpdate VALUES(130120391150,11,'H251');
INSERT INTO testUpdate VALUES(130120391250,12,'');
COMMIT;

sqlite> with fixes as
 (select indexInter, code
  from testUpdate
  where indexInter > 2)
 select indexRow, indexInter, code, 
       (select code 
        from fixes
        where fixes.indexInter+1 = testUpdate.indexInter) as edit
 from testUpdate;
indexRow      indexInter  code    edit 
------------  ----------  ------  -----
130120390150  1           H1961        
130120390250  2           H8033        
130120390350  3           H1732        
130120390450  4           H3117   H1732
130120390470              punct3       
130120390550  5           H7969   H3117
130120390650  6           H398    H7969
130120390750  7           H8354   H398 
130120390770              punct2       
130120390850  8                   H8354
130120390950  9           H3559        
130120391050  10                  H3559
130120391150  11          H251         
130120391250  12                  H251 

sqlite> begin transaction;
sqlite> with fixes as 
  (select indexInter, code
   from testUpdate
   where indexInter > 2)
  update testUpdate
  set code = (select code
              from fixes
              where fixes.indexInter+1 = testUpdate.indexInter) 
  where indexInter > 3 
  returning *;
indexRow      indexInter  code 
------------  ----------  -----
130120390450  4           H1732
130120390550  5           H1732
130120390650  6           H1732
130120390750  7           H1732
130120390850  8           H1732
130120390950  9           H1732
130120391050  10          H1732
130120391150  11          H1732
130120391250  12          H1732
sqlite> rollback;

使用下面的更新使它工作,但为什么使用上面的更新它不工作呢?

sqlite> begin transaction;
sqlite> with fixes as
  (select indexInter, code
   from testUpdate
   where indexInter > 2)
  update testUpdate
  set code = fixes.code
  from fixes
  where fixes.indexInter+1 = testUpdate.indexInter
    and testUpdate.indexInter > 3
  returning *;
indexRow      indexInter  code 
------------  ----------  -----
130120390450  4           H1732
130120390550  5           H3117
130120390650  6           H7969
130120390750  7           H398 
130120390850  8           H8354
130120390950  9                
130120391050  10          H3559
130120391150  11               
130120391250  12          H251 
sqlite> select * from testUpdate;
indexRow      indexInter  code  
------------  ----------  ------
130120390150  1           H1961 
130120390250  2           H8033 
130120390350  3           H1732 
130120390450  4           H1732 
130120390470              punct3
130120390550  5           H3117 
130120390650  6           H7969 
130120390750  7           H398  
130120390770              punct2
130120390850  8           H8354 
130120390950  9                 
130120391050  10          H3559 
130120391150  11                
130120391250  12          H251
kognpnkq

kognpnkq1#

在第二个查询中,CTE只执行一次,从数据表的初始数据列传回预期的数据列。
但在第一个查询中,由于存在相关子查询,将对需要更新的表中的每一行执行CTE:

select code from fixes where fixes.indexInter+1 = testUpdate.indexInter

这意味着在更新第一行后,将再次执行CTE,但这次它选择更新了1行的表。
然后再次执行,并从更新了2行的表中进行选择,依此类推。

相关问题