2011-09-10 47 views
15

Có bất kỳ câu lệnh vòng lặp nào trong SQLite như FOR .. in .. LOOP hoặc một cái gì đó tương tự không? Tôi có hai cột StartRange, EndRange và tôi cần chèn toàn bộ chuỗi trong bảng khác. Vì vậy, nếu StartRange là 1 và EndRange là 3 cần thiết để thực hiện ba lần chèn có giá trị, chứa 1, 2, 3.Câu lệnh lặp SQLite?

+2

Tôi sợ bạn sẽ cần phải viết một số mã bắt buộc phải làm nó, SQL nói chung là một ngôn ngữ khai báo và chỉ các phần mở rộng của nó (như T-SQL, SQL/PL, vv) hỗ trợ các cấu trúc điều khiển luồng như vòng lặp. Tuy nhiên, nếu cần phải thực hiện việc chèn trong một lần chạy bằng cách sử dụng các giao dịch SQLite. –

+0

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

+0

Điều này có nên được chuyển đến dba.stackexchange.com không? – anddam

Trả lời

8

Bạn có thể làm điều này trong SQL thẳng nếu bạn có thêm một bảng chứa tất cả các số nguyên mà bạn cần.

Giả sử bạn StartRangeEndRange phạm vi từ một đến mười và bạn có một bảng như thế này:

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

Bảng này chỉ đơn giản có chứa tất cả các số nguyên có thể là bạn cần (có nghĩa là mật thông qua mười).

Sau đó, nếu bạn cũng có điều này:

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

Bạn có thể làm Phụ trang của bạn vào target với một tham gia:

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

Kết quả là thế này:

sqlite> select * from target; 
i 
1 
2 
3 

Dĩ nhiên t thực của bạn sẽ có nhiều hàng hơn, do đó bạn muốn một mệnh đề WHERE để giới hạn hàng nào trong số t bạn xem.

Những thứ tương tự thường được thực hiện với các ngày (tra cứu "bảng lịch"). Vì vậy, nếu phạm vi của bạn là nhỏ (đối với một số định nghĩa của nhỏ) sau đó tạo bảng ints một lần, thêm chỉ mục vào đó và sử dụng kỹ thuật trên để thực hiện tất cả các quyền INSERT ngay bên trong cơ sở dữ liệu. Cơ sở dữ liệu khác có cách riêng của họ (chẳng hạn như PostgreSQL's generate_series) để làm điều này loại mà không cần một bảng rõ ràng ints nhưng SQLite là (cố ý) hạn chế.

SQL thường được thiết lập dựa trên các vòng lặp không phải là tự nhiên. Điều gì là tự nhiên là xây dựng các bộ thích hợp bằng cách mô tả những gì bạn cần. OTOH, đôi khi các hành động không tự nhiên là cần thiết và hợp lý.

Tôi không biết điều này có hợp lý với đơn đăng ký của bạn hay không, tôi chỉ nghĩ tôi sẽ chứng minh cách thực hiện. Nếu cách tiếp cận này không có ý nghĩa trong trường hợp của bạn thì bạn có thể tạo ra một loạt các câu lệnh INSERT bên ngoài cơ sở dữ liệu.

+0

Các bảng SQLite có các số hàng có thể được sử dụng trong các truy vấn. – reinierpost

+0

@reinierpost Bạn đang đề cập đến 'rowid'? –

+0

Có. (và với tên của bạn, nó là * vẫn * quá ngắn) – reinierpost

14

Bạn có thể tạo vòng lặp trong SQL bằng trình kích hoạt đệ quy.Sử dụng mu quá ngắn '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); 

chúng ta cần phải kích hoạt trigger đệ quy trong SQLite:

sqlite> PRAGMA recursive_triggers = on; 

Hãy kích hoạt tạm thời để lặp đến khi kết thúc của dãy núi này:

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; 

Đá tắt:

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

Đây là ma thuật đen tôi cần. Cảm ơn cậu! –

2

Rõ ràng cấu trúc lặp trong SQLite là mệnh đề WITH RECURSIVE. Liên kết tài liệu đó có mẫu đếm đến mười mã, một bộ vẽ Mandelbrot, và một bộ giải đố Sudoku, tất cả trong SQL thuần túy. Dưới đây là một truy vấn SQLite rằng tính dãy Fibonacci để cung cấp cho bạn một cảm giác về nó:

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

Và đây là một 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; 
Các vấn đề liên quan