2011-09-10 238 views
15

SQLite中是否有像FOR .. in .. LOOP或类似的东西的循环语句?我有两列StartRange, EndRange,我需要在其他表中插入整个序列。因此,如果StartRange为1且EndRange为3,则需要制作三个带有值的插入,其中包含1, 2, 3SQLite循环语句?

+2

恐怕你需要编写一些必要的代码,这样做它通常是一种声明性语言,只有它的扩展(如T-SQL,SQL/PL等)支持循环等控制流结构。但是,如果应该很容易,可以使用SQLite事务在一次运行中执行插入操作。 –

+0

Perl/Python/Ruby-script-to-the-rescue! :) – 2011-09-10 09:17:07

+0

这应该被移动到dba.stackexchange.com? – anddam

回答

8

如果你有一个额外的表,它包含你需要的所有整数,你可以在直接SQL中做这种事情。

假设一个十之间的StartRangeEndRange范围内,你有一个表是这样的:

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); 

你可以做你插入到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你看。

类似的事情通常与日期(查找“日历表”)。

所以,如果你的范围小(对于一些定义),然后生成您的ints表一次,一个索引添加到它,并使用上述技术做对数据库内的所有插件。其他数据库有自己的方式(如PostgreSQL的generate_series)做这种事情,而不需要明确的ints表,但SQLite(有意)是有限的。

SQL通常是基于集合的,所以循环并不自然。很自然的是通过描述你需要的东西来构建适当的集合。 OTOH,有时不自然的行为是必要和明智的。

我不知道这对你的应用程序是否有意义,我只是想我会证明它是如何完成的。如果这种方法在你的情况下没有意义,那么你可以在数据库之外生成一堆INSERT语句。

+0

SQLite表具有可用于查询的行号。 – reinierpost

+0

@reinierpost你指的是'rowid'吗? –

+0

是的。 (和你的名字,它*仍然*太短) – reinierpost

14

您可以使用递归触发器在SQL中创建循环。使用亩太短的架构

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> 
+2

这是我需要的黑魔法。谢谢哥们! –

2

显然,SQLite中的循环结构是WITH RECURSIVE子句。 该文档链接包含样本计数到十位的代码,一个Mandelbrot设置绘图仪和一个Sudoku拼图求解器,都在纯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,... 

这里是一个Sieve of Eratosthenes

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;