SQLite 循环语句?

发布于 2024-12-03 21:35:45 字数 203 浏览 2 评论 0原文

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

Is there any loop statements in SQLite like FOR .. in .. LOOP or something like that? I have two columns StartRange, EndRange and I need to insert a whole sequence in the other table. So if StartRange is 1 and EndRange is 3 it's necessary to make three inserts with the values 1, 2, 3.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

别理我 2024-12-10 21:35:45

显然,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;

Apparently the looping construct in SQLite is the WITH RECURSIVE clause.
That documentation link has sample count-to-ten code, a Mandelbrot set plotter, and a Sudoku puzzle solver, all in pure SQL.
Here's an SQLite query that computes the Fibonacci sequence to give you a feel for it:

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

And here's a 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;
狼性发作 2024-12-10 21:35:45

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

You can make loops in SQL with recursive triggers. Using mu is too short's schema

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

we need to enable recursive triggers in SQLite:

sqlite> PRAGMA recursive_triggers = on;

Make a temporary trigger to loop up to the end of the range:

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;

Kick it off:

sqlite> insert into target values ((select t.startrange from t));
sqlite> select * from target;
3
2
1
sqlite> 
涙—继续流 2024-12-10 21:35:45

如果您有一个额外的表来保存您需要的所有整数,则可以直接使用 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);

您可以使用连接将 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 行。

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

因此,如果您的范围很小(对于的某些定义),则生成一次ints表,向其中添加索引,然后使用上述技术来执行所有插入就在数据库里面。其他数据库有自己的方式(例如PostgreSQL的 generate_series)不需要显式的ints表就能完成这类事情,但SQLite(有意)受到限制。

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

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

You can do this sort of thing in straight SQL if you have an extra table that holds all the integers that you need.

Suppose your StartRange and EndRange range between one and ten and you have a table like this:

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

This table simply contains all the possible integers that you need (i.e. one through ten).

Then if you also have this:

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

You can do your INSERTs into target with a join:

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

The result is this:

sqlite> select * from target;
i
1
2
3

Of course your real t would have more rows so you'd want a WHERE clause to limit which row of t you look at.

Similar things are often done with dates (look up "calendar tables").

So if your ranges are small (for some definition of small) then generate your ints table once, add an index to it, and use the above technique to do all the INSERTs right inside the database. Other databases have their own ways (such as PostgreSQL's generate_series) to do this sort of thing without need an explicit ints table but SQLite is (intentionally) limited.

SQL is generally set-based so loops aren't natural. What is natural is building the appropriate sets by describing what you need. OTOH, sometimes unnatural acts are necessary and sensible.

I don't know if this makes sense for your application, I just thought I'd demonstrate how it can be done. If this approach doesn't make sense in your case then you can generate a bunch of INSERT statements outside the database.

梦里梦着梦中梦 2024-12-10 21:35:45

SQL 中不需要循环,因为没有 WHERE 子句
该命令将对表中的每一行执行。
只需使用:(

Update your_table set Endrange=Startrange+2

并提交更改),因此 Endrange 列中的每个数字都会比 Startrange 列中的数字大 2。

There is no need for loops in SQL, because without the WHERE clause
the command will be executed for every row in the table.
Use simply:

Update your_table set Endrange=Startrange+2

(and commit the changes), so each number in the Endrange column will be greater by 2 compared to the number in the Startrange column.

怎言笑 2024-12-10 21:35:45

可以将数字序列生成为虚拟表,并可以选择开始、停止和步骤。

select value, start, stop, step
from generate_series
where start=0 and stop=10 and step=1;

此选择可能会插入到您的表中:

create table yourtable(value integer);
insert into yourtable(value)
select value ... -- as in my example above.

祝你好运,快乐的 sqlite

a sequence of numbers can be generated as a virtual table, with start, stop and step you choose.

select value, start, stop, step
from generate_series
where start=0 and stop=10 and step=1;

this select may be inserted in your table as:

create table yourtable(value integer);
insert into yourtable(value)
select value ... -- as in my example above.

good luck and happy sqlite

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文