2011-09-10 14 views
15

SQLite'de FOR .. in .. LOOP gibi bir döngü ifadesi var mı ya da böyle bir şey var mı? İki sütun StartRange, EndRange var ve diğer tabloya tüm diziyi eklemek gerekiyor. Bu nedenle, StartRange 1 ve EndRange ise 3 değeri olan üç ekleme yapmak için 1, 2, 3 içerir.SQLite döngü ifadeleri?

+2

Senden tek bazı zorunlu kod yazmak gerekir korkuyorum Bu, SQL genellikle bir bildirim dili ve sadece onun uzantıları (T-SQL, SQL/PL vb gibi) döngüler gibi kontrol akış yapıları destekler. Bununla birlikte, SQLite işlemlerini kullanarak tek bir işlemde ekleme yapmak kolay olsa da. –

+0

Perl/Python/Ruby-komut dosyası-kurtarma! :) –

+0

Bu dba.stackexchange.com'a taşınmalı mı? – anddam

cevap

8

İhtiyacınız olan tüm tam sayıları içeren fazladan bir tablonuz varsa, bu tür bir şeyi doğrudan SQL'de yapabilirsiniz.

bir ile on arasında StartRange ve EndRange aralığı varsayalım ve bir tablo böyle vardır:

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

Bu tablo sadece size gerekli olan tüm olası tamsayılar (on temel yani bir) içerir.

Sonra da bu varsa:

Sen ile target içine ınsert'ler yapabilirsiniz
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); 

bir katılmak: Elbette

sqlite> select * from target; 
i 
1 
2 
3 

:

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

sonuç şudur Gerçek t’un daha fazla satırı olur, böylece hangi satırın sınırlandıracağını bir WHERE yan tümcesi t göz atın.

Benzer şeyler genellikle tarihlerle yapılır ("takvim tabloları" konusuna bakın).

Yani aralıkları daha sonra, bir kez ints tablo oluşturmak buna bir dizin ekleyin ve sağ veritabanı içindeki tüm ınsert'ler yapmak için yukarıdaki tekniği kullanır (küçük bazı tanımı için) küçük ise. Diğer veritabanları, kendi türlerine (PostgreSQL'in generate_series gibi) açık bir ints tablosuna ihtiyaç duymadan bu tür bir şeyi yapmaları için yeterlidir ancak SQLite (bilerek) sınırlıdır.

SQL genellikle ayar tabanlı olduğundan döngüler doğal değildir. Doğal olan, neye ihtiyacınız olduğunu tanımlayarak uygun setleri oluşturuyor. OTOH, bazen doğal olmayan eylemler gereklidir ve mantıklıdır.

Bunun sizin uygulamanız için anlamlı olup olmadığını bilmiyorum, sadece nasıl yapılabileceğini göstereyim diye düşündüm. Bu yaklaşım sizin durumunuzda mantıklı değilse, o zaman veritabanının dışında bir grup INSERT ifadesi oluşturabilirsiniz.

+0

SQLite tablolarında, sorgularda kullanılabilen sıra numaraları bulunur. – reinierpost

+0

@reinierpost "rowid" ifadesini kullanıyor musunuz? –

+0

Evet. (ve isminizle, * hala * çok kısa) – reinierpost

14

Yinelemeli tetikleyicilerle SQL'de döngüler yapabilirsiniz.

sqlite> PRAGMA recursive_triggers = on; 

aralığının sonuna kadar döngü geçici tetikleyici yapın:

mu Kullanılması biz SQLite'ta özyinelemeli tetikler etkinleştirmeniz gerekir 'ın şema

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

çok kısa

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 kapalı:

sqlite> insert into target values ((select t.startrange from t)); 
sqlite> select * from target; 
3 
2 
1 
sqlite> 
+2

İşte ihtiyacım olan kara büyü. Sağol kanka! –

2

Görünüşe göre SQLite içindeki döngü yapısı WITH RECURSIVE yan tümcesidir. Bu dokümantasyon bağlantısında, tümü salt SQL'de örnek bire-bir kod, bir Mandelbrot set plotter ve bir Sudoku bulmaca çözücüsü vardır. İşte Fibonacci dizisini hesaplar bir SQLite sorgu bunun için size bir fikir vermek için verilmiştir:

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

Ve burada bir 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;