SQLite循环语句?

时间:2011-09-10 09:10:33

标签: sql sqlite loops for-loop range

SQLite中有任何循环语句,如FOR .. in .. LOOP或类似的东西吗?我有两列StartRange, EndRange,我需要在其他表中插入整个序列。因此,如果StartRange为1且EndRange为3,则必须使用值生成三个插入,包含1, 2, 3

3 个答案:

答案 0 :(得分:18)

您可以使用递归触发器在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> 

答案 1 :(得分:10)

如果你有一个包含你需要的所有整数的额外表,你可以在直接SQL中执行此类操作。

假设您的StartRangeEndRange介于1到10之间,并且您有一个这样的表:

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

此表只包含您需要的所有可能的整数(即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);

您可以使用join:

将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语句。

答案 2 :(得分:6)

显然,SQLite中的循环结构是{​​{3}}子句。 该文档链接包含样本数到十的代码,一个Mandelbrot set plotter和一个Sudoku难题解算器,所有这些都在纯SQL中。 这是一个SQLite查询,它计算Fibonacci序列,让您感受到它:

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,...

这是一个WITH RECURSIVE

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;