2011-09-10 47 views
15

¿Hay instrucciones de bucle en SQLite como FOR .. in .. LOOP o algo así? Tengo dos columnas StartRange, EndRange y necesito insertar secuencia completa en otra tabla. Entonces, si StartRange es 1 y EndRange es 3, es necesario hacer tres inserciones con valor, contiene 1, 2, 3.declaraciones de bucle SQLite?

+2

Me temo que tendrá que escribir un código imperativo hacer es decir, SQL generalmente es un lenguaje declarativo y solo sus extensiones (como T-SQL, SQL/PL, etc.) admiten estructuras de flujo de control como bucles. Sin embargo, debería ser fácil realizar la inserción en una ejecución mediante el uso de transacciones SQLite. –

+0

Perl/Python/Ruby-script-to-the-rescue! :) –

+0

¿Debería ser movido a dba.stackexchange.com? – anddam

Respuesta

8

Puede hacer este tipo de cosas en SQL directo si tiene una tabla adicional que contiene todos los enteros que necesita.

Suponga que su StartRange y EndRange rango de entre uno y diez y usted tiene una tabla como la siguiente:

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

Esta tabla contiene simplemente todos los posibles números enteros que usted necesita (es decir, uno al diez).

Entonces si también tiene esto:

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

Usted puede hacer sus inserta en target con una combinación:

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

El resultado es este:

sqlite> select * from target; 
i 
1 
2 
3 

Por supuesto su verdadero t tendría más filas, por lo que querría una cláusula WHERE para limitar qué fila de t que miras.

A menudo se hacen cosas similares con las fechas (busque "tablas de calendario").

Así que si sus rangos son pequeñas (por alguna definición de pequeña ) y luego generar la tabla de ints vez, añadir un índice a la misma, y ​​el uso de la técnica anterior para hacer todas las inserciones de la derecha dentro de la base de datos. Otras bases de datos tienen sus propias formas (como PostgreSQL generate_series) para hacer este tipo de cosas sin necesidad de una tabla explícita ints, pero SQLite es (intencionalmente) limitado.

SQL está generalmente basado en conjunto, por lo que los bucles no son naturales. Lo natural es construir los conjuntos apropiados mediante la descripción de lo que necesita. OTOH, a veces los actos antinaturales son necesarios y sensibles.

No sé si esto tiene sentido para su aplicación, simplemente pensé que demostraría cómo se puede hacer. Si este enfoque no tiene sentido en su caso, entonces puede generar un grupo de instrucciones INSERT fuera de la base de datos.

+0

Las tablas de SQLite tienen números de fila que se pueden usar en las consultas. – reinierpost

+0

@reinierpost ¿Te refieres a 'rowid'? –

+0

Sí. (y con su nombre, es * todavía * demasiado corto) – reinierpost

14

Puede hacer bucles en SQL con activadores recursivos.Usando mu es demasiado corta 's esquema

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

que necesitamos para permitir desencadenadores recursivos en SQLite:

sqlite> PRAGMA recursive_triggers = on; 

Hacer un disparador temporal de bucle hasta el final de la gama:

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 lo apaga:

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

Aquí está la magia negra que necesitaba. ¡Gracias amigo! –

2

Aparentemente, la construcción de bucle en SQLite es la cláusula WITH RECURSIVE. Ese enlace de documentación tiene código de cuenta de muestra a diez, un trazador de conjunto de Mandelbrot y un solucionador de rompecabezas de Sudoku, todo en SQL puro. He aquí una consulta de SQLite que calcula la sucesión de Fibonacci para darle una idea de ella:

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

Y aquí hay un 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; 
Cuestiones relacionadas