SQLiteにFOR .. in .. LOOP
などのループステートメントはありますか? 2つの列StartRange, EndRange
があり、シーケンス全体を他のテーブルに挿入する必要があります。したがって、StartRange
が1でEndRange
が3の場合、1, 2, 3
を含む、値を持つ3つの挿入を行う必要があります。
必要なすべての整数を保持する追加のテーブルがある場合は、ストレートSQLでこの種のことを行うことができます。
StartRange
とEndRange
の範囲が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ステートメントを生成できます。
再帰トリガーを使用して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>
どうやら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;