web-dev-qa-db-ja.com

SQLiteループステートメント?

SQLiteにFOR .. in .. LOOPなどのループステートメントはありますか? 2つの列StartRange, EndRangeがあり、シーケンス全体を他のテーブルに挿入する必要があります。したがって、StartRangeが1でEndRangeが3の場合、1, 2, 3を含む、値を持つ3つの挿入を行う必要があります。

22
kseen

必要なすべての整数を保持する追加のテーブルがある場合は、ストレート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);

targetへのINSERTを結合で行うことができます:

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テーブルを1回生成し、それにインデックスを追加します。上記の手法を使用して、データベース内ですべてのINSERTを実行します。他のデータベースには、明示的なintsテーブルを必要とせずにこの種のことを行う独自の方法(PostgreSQLの generate_series など)がありますが、SQLiteは(意図的に)制限されています。

SQLは一般にセットベースであるため、ループは自然ではありません。自然なことは、必要なものを説明することによって適切なセットを構築することです。 OTOH、時々不自然な行為が必要で賢明です。

これがあなたのアプリケーションにとって意味があるかどうかは分かりませんが、私はそれがどのようにしてできるかを示すつもりだと思っていました。このアプローチがあなたのケースで意味をなさない場合は、データベースの外部で一連のINSERTステートメントを生成できます。

11
mu is too short

再帰トリガーを使用して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> 
20
Doug Currie

どうやらSQLiteのループ構造は WITH RECURSIVE 句です。このドキュメントリンクには、サンプルのcount-to-tenコード、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;
10
rob