SQLITE - 插入...在哪里 - 如何强制动态行为

问题描述 投票:0回答:1

我在 WHERE 条件下尝试了 INSERT。现在, WHERE 将取决于每个新插入的记录,例如

WHERE NOT EXISTS (select ... from <table I am inserting records into>)
.

但是,WHERE 子句被评估一次,并且不考虑每个新插入的记录。

我知道 INSERT OR IGNORE,或 INSERT OR UPDATE 或 UPSERT ... 然而,在我的例子中,WHERE 子句会比仅仅验证密钥的存在更复杂。

问题是查询优化器永远只评估一次WHERE,而不是一条一条地考虑新插入的记录。很公平。

问题:有没有办法强制查询优化器在插入后立即考虑每条记录?

作为一个(有点理论性的)例子:从递归生成的数列中引入质数,WHERE 条件声明它不能被表中已经存在的任何(质数)数相除。密码 WON'T work;它将一共介绍19个数字。

CREATE TABLE pnumbers (pnumber number primary key);

with r as 
(select 2 as n union all select n+1 as n from r where n < 20)
insert into pnumbers
select n from r where not exists 
(select pnumber from pnumbers pn where r.n % pn.pnumber = 0 );

附言 相反, DELETE .. WHERE 工作完美 并且速度非常快。下面的代码在我的游戏笔记本电脑上仅用 90 秒就消除了 1000 万个连续数字中的非素数——(然而,这不是我的想法):

delete from pnumbers  where exists (select pnumber from pnumbers pn2 
where pn2.pnumber <= sqrt(pnumbers.pnumber) and pnumbers.pnumber % pn2.pnumber = 0);  
sqlite dynamic insert where-clause behavior
1个回答
0
投票

问题是查询优化器评估了一次 WHERE 永远

不,这不是真的。

WHERE
子句对
r
的每一行求值一次,因为
EXISTS
的子查询是一个 correlated 子查询

问题有点不一样

在任何

INSERT INTO ... SELECT...
语句中,首先执行
SELECT...
语句,完成后返回的结果集被插入到表中。

这意味着对于您的理论示例,在该语句返回之前不会插入表

pnumbers

with r as 
(select 2 as n union all select n+1 as n from r where n < 20)
select n from r where not exists 
(select pnumber from pnumbers pn where r.n % pn.pnumber = 0 ); 

在上面的语句中对表

pnumbers
的任何引用都将访问一个空表,因为尚未插入任何行。
这就是为什么这条语句返回
r
的所有行。

确实在 SQLite 的INSERT 的文档中没有清楚地概述这种行为,但这是意思:

为每行数据插入一个新条目到表中 通过执行 SELECT 语句返回

© www.soinside.com 2019 - 2024. All rights reserved.