Pl / PgSQL,插入两个表,一个带有标题行

时间:2012-05-30 09:01:35

标签: sql postgresql plpgsql

进行以下插入的最佳方法是什么?我环顾四周,我有点卡住了。

我目前拥有的表格(插入)

| 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是从序列(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;

有没有更好的方法,或上述是否可以完成此类插入的唯一方法?

1 个答案:

答案 0 :(得分: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)