2012-05-30 34 views
3

會是什麼打算這樣做的以下插入的最佳途徑。我環顧四周,我有點卡住了。PL/pgSQL裏,插入到兩個表,一個有標題行

表我目前有(插入)

| id | order_id | item_id | type | group | 
| 1 | 1  | 1  | 2 | 1  | <- type 2 represents a "header" item, or a "kit" 
| 2 | 1  | 2  | 1 | 1  | <- type 1 represents a member of the "kit" 
| 3 | 1  | 3  | 1 | 1  | 
| 4 | 1  | 4  | 2 | 2  | <- New group means new kit 
| 5 | 1  | 2  | 1 | 2  | 
| 6 | 1  | 5  | 1 | 2  | 

我需要插入這些項目分爲以下兩個表:
1)item_entry

| id | mode | tmplt_id | item_id | parent_item_entry_id | 
| 1 | 1 | 1  | NULL | NULL     | <- This is a header line, mode 1 
| 2 | 2 | NULL  | 2  | 1     | <- This is a sub line, mode 2 
| 3 | 2 | NULL  | 3  | 1     | <- parent_item_entry_id references the header it belongs to 
| 4 | 1 | 4  | NULL | NULL     | 
| 5 | 2 | NULL  | 2  | 4     | 
| 6 | 2 | NULL  | 5  | 4     | 

2)item_entry_details

| id | item_entry_id | order_id | group | 
| 1 | 1    | 1  | 1  | 
| 2 | 4    | 1  | 2  | <- only header information is necessary 

當然,item_entry.id是由f的序列(item_entry_id_seq)。有沒有一種方法可以讓這個工作起作用?我目前通過每個組環,第一通過基團中的每個項目分配一個NEXTVAL()到一個變量,然後我循環,寫入表。

FOR recGroup IN SELECT DISTINCT group FROM insert LOOP 
    intParentItemEntryID := nextval('item_entry_id_seq'); 
    FOR recLine IN SELECT * FROM insert LOOP 
    INSERT INTO item_entry VALUES (CASE intParentItemEntryID/DEFAULT, CASE 1/2, CASE recLine.item_id/NULL, CASE NULL/recLine.item_id, CASE NULL/intParentItemEntryID) 
    INSERT INTO item_entry_details VALUES (DEFAULT, intParentItemEntryID, recLine.order_id, recLine.group); 
    END LOOP; 
END LOOP; 

有沒有更好的辦法,或者是上面這種插入方式的唯一方法?

回答

4

這裏不需要程序代碼「一次一行」,只需簡單的舊sql就足夠了。

-- create the tables that the OP did not provide 
DROP TABLE the_input; 
CREATE TABLE the_input 
    (id INTEGER NOT NULL PRIMARY KEY 
    , order_id INTEGER NOT NULL 
    , item_id INTEGER NOT NULL 
    , ztype INTEGER NOT NULL 
    , zgroup INTEGER NOT NULL 
    ); 
DROP TABLE target1 ; 
CREATE TABLE target1 
    (id INTEGER NOT NULL 
    , zmode INTEGER NOT NULL 
    , tmplt_id INTEGER  
    , item_id INTEGER  
    , parent_item_entry_id INTEGER 
    ); 
DROP TABLE target2 ; 
CREATE TABLE target2 
    (id SERIAL NOT NULL 
    , item_entry_id INTEGER NOT NULL 
    , order_id INTEGER NOT NULL 
    , zgroup INTEGER NOT NULL 
    ); 

-- fil it up ... 
INSERT INTO the_input  
(id, order_id, item_id, ztype, zgroup) VALUES 
(1 , 1  , 1  , 2 , 1 ) -- <- type 2 represents a "header" item, or a "kit" 
,(2 , 1  , 2  , 1 , 1 ) -- <- type 1 represents a member of the "kit" 
,(3 , 1  , 3  , 1 , 1 ) -- 
,(4 , 1  , 4  , 2 , 2 ) -- <- New group means new kit 
,(5 , 1  , 2  , 1 , 2 ) -- 
,(6 , 1  , 5  , 1 , 2 ) -- 
    ; 

-- Do the inserts. 
INSERT INTO target1(id,zmode,tmplt_id,item_id,parent_item_entry_id) 
SELECT i1.id, 1, i1.id, NULL, NULL 
FROM the_input i1 
WHERE i1.ztype=2 
UNION ALL 
SELECT i2.id, 2, NULL, i2.id, ip.item_id 
FROM the_input i2 
JOIN the_input ip ON ip.zgroup = i2.zgroup AND ip.ztype=2 
WHERE i2.ztype=1 
    ; 
INSERT INTO target2(item_entry_id,order_id,zgroup) 
SELECT DISTINCT MIN(item_id),order_id, zgroup 
FROM the_input i1 
WHERE i1.ztype=2 
GROUP BY order_id,zgroup 
    ; 
SELECT * FROM target1 
ORDER BY id; 

SELECT * FROM target2 
ORDER BY id; 

結果:

NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "the_input_pkey" for table "the_input" 
CREATE TABLE 
INSERT 0 6 
DROP TABLE 
CREATE TABLE 
INSERT 0 6 
id | zmode | tmplt_id | item_id | parent_item_entry_id 
----+-------+----------+---------+---------------------- 
    1 |  1 |  1 |   |      
    2 |  2 |   |  2 |     1 
    3 |  2 |   |  3 |     1 
    4 |  1 |  4 |   |      
    5 |  2 |   |  5 |     4 
    6 |  2 |   |  6 |     4 
(6 rows) 

DROP TABLE 
NOTICE: CREATE TABLE will create implicit sequence "target2_id_seq" for serial column "target2.id" 
CREATE TABLE 
INSERT 0 2 
id | item_entry_id | order_id | zgroup 
----+---------------+----------+-------- 
    1 |    4 |  1 |  2 
    2 |    1 |  1 |  1 
(2 rows) 
+0

感謝您的幫助!我知道必須有一種方法,我無法弄清楚。 – BedderDanu

相關問題