SQLite 循环语句?

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

SQLite 中是否有类似

FOR .. in .. LOOP
之类的循环语句?我有两列
StartRange, EndRange
,我需要在另一个表中插入整个序列。因此,如果
StartRange
为 1 并且
EndRange
为 3,则需要使用值
1, 2, 3
进行三个插入。

sql sqlite loops for-loop range
4个回答
24
投票

显然 SQLite 中的循环构造是 WITH RECURSIVE 子句。 该文档链接包含从数到十的示例代码、Mandelbrot 集绘图仪和数独谜题求解器,全部采用纯 SQL 语言。 下面是一个计算斐波那契数列的 SQLite 查询,让您感受一下:

sqlite> WITH RECURSIVE
   ...>   fibo (curr, next)
   ...> AS
   ...>   ( SELECT 1,1
   ...>     UNION ALL
   ...>     SELECT next, curr+next FROM fibo
   ...>     LIMIT 100 )
   ...> SELECT group_concat(curr) FROM fibo;
1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,...

这是埃拉托色尼筛

begin transaction;

drop table if exists naturals;
create table naturals
( n integer unique primary key asc,
  isprime bool,
  factor integer);

with recursive
  nn (n)
as (
  select 2
  union all
  select n+1 as newn from nn
  where newn < 1e4
)
insert into naturals
select n, 1, null from nn;

insert or replace into naturals
  with recursive
    product (prime,composite)
  as (
    select n, n*n as sqr
      from naturals
      where sqr <= (select max(n) from naturals)
    union all
    select prime, composite+prime as prod
    from
      product
    where
      prod <= (select max(n) from naturals)
  )
select n, 0, prime
from product join naturals
  on (product.composite = naturals.n)
;
commit;

20
投票

您可以使用递归触发器在 SQL 中创建循环。使用mu太短了的模式

sqlite> create table t (startrange int not null, endrange int not null);
sqlite> insert into t values(1, 3);
sqlite> create table target (i int not null);

我们需要在 SQLite 中启用递归触发器:

sqlite> PRAGMA recursive_triggers = on;

制作一个临时触发器以循环到范围的末尾:

sqlite> create temp trigger ttrig
   ...> before insert on target
   ...> when new.i < (select t.endrange from t) begin
   ...> insert into target values (new.i + 1);
   ...> end;

开始吧:

sqlite> insert into target values ((select t.startrange from t));
sqlite> select * from target;
3
2
1
sqlite> 

15
投票

如果您有一个额外的表来保存您需要的所有整数,则可以直接使用 SQL 执行此类操作。

假设您的

StartRange
EndRange
范围在 1 到 10 之间,并且您有一个如下所示的表格:

sqlite> select i from ints;
i
1
.
.
.
10

此表仅包含您需要的所有可能的整数(即一到十)。

那么如果你也有这个:

sqlite> create table t (startrange int not null, endrange int not null);
sqlite> insert into t values(1, 3);
sqlite> create table target (i int not null);

您可以通过连接将 INSERT 插入

target

insert into target (i)
select ints.i
from ints join t on (ints.i >= t.startrange and ints.i <= t.endrange)

结果是这样的:

sqlite> select * from target;
i
1
2
3

当然,您真正的

t
会有更多行,因此您需要一个 WHERE 子句来限制您查看
t
的哪一行。

类似的事情经常用日期来完成(查找“日历表”)。

因此,如果您的范围很小(对于 small 的某些定义),则生成一次

ints
表,向其添加索引,然后使用上述技术在数据库内执行所有 INSERT。其他数据库有自己的方法(例如 PostgreSQL 的
generate_series
)来执行此类操作,而不需要显式
ints
表,但 SQLite (有意)受到限制。

SQL 通常是基于集合的,因此循环并不自然。自然的做法是通过描述您的需求来构建适当的集合。 OTOH,有时不自然的行为是必要且明智的。

我不知道这对您的应用程序是否有意义,我只是想演示一下如何做到这一点。如果这种方法对您的情况没有意义,那么您可以在数据库外部生成一堆 INSERT 语句。


0
投票

SQL 中不需要 FOR LOOPS,因为没有 WHERE 子句 该命令将对表中的每一行执行。 只需使用:“Update your_table set Endrange=Startrange+2”(并提交更改),因此 Endrange 列中的每个数字将比 Startrange 列中的数字大 2。

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