2015-02-09 56 views
2

我想插入多个(2)行到Postgres的表中,并使用WITH ROWS AS返回的ID插入到另一个表(列id_1和​​second_table),并返回 id作为查询的最终结果。Postgres从表中插入多个返回值作为

first_table是主要数据收集,而second_table基本上只是将两个first_table条目链接在一起。

这里是我想要做的要点:

WITH row AS (
     INSERT INTO first_table (some_data, more_data) 
     VALUES (DEFAULT, DEFAULT), (DEFAULT, DEFAULT) 
     RETURNING first_table_id 
     ) 
INSERT INTO second_table (id_1, id_2, other_data) 
VALUES (???, ???, DEFAULT) 
RETURNING second_table_id 

我如何使用Node.js和node-pg模块;我知道这可以在Node.js中完成,方法是让第一个查询返回WITH ROWS AS返回的两行,然后使用下一个插入的两个ID运行另一个准备好的语句。

我不确定我是否可以通过触发器来执行此操作,因为ON INSERT只有一行。也许它会有两个,因为这些行在同一个事务中插入到first_table中,但是我一般没有丰富的Postgres/SQL经验,所以我不知道如何通过触发器来做到这一点。

我遇到的问题是,WITH ROWS AS语句返回2行(显然是打算),但我不知道如何在下一个插入中独立访问每行,并且我感觉它不是不可能。

可这在单个查询来完成,还是我用于此触发器或Node.js的?

回答

3

第二次插入需要是INSERT INTO ... SELECT ... FROM first_cte。如果你可以做出一个假设,那第二个生成的id比第一个(或者至少是不同的 - 比如 - 如果你使用PostgreSQL的serial,或者直接使用一个序列)大,你可以使用聚合:

WITH rows AS (
    INSERT INTO first_table (some_data, more_data) 
    VALUES (DEFAULT, DEFAULT), (DEFAULT, DEFAULT) 
    RETURNING first_table_id 
) 
INSERT INTO second_table (id_1, id_2) 
SELECT min(first_table_id), max(first_table_id) 
FROM rows 
RETURNING second_table_id 

需要注意的是,省略other_data:你不能在INSERT INTO ... SELECT ...使用DEFAULT

对于更广泛的解决方案,你可以使用数组:

WITH rows AS (
    INSERT INTO first_table (some_data, more_data) 
    VALUES (DEFAULT, DEFAULT), (DEFAULT, DEFAULT) 
    RETURNING first_table_id 
) 
INSERT INTO second_table (id_1, id_2, other_data) 
SELECT first_table_ids[1], first_table_ids[2], 5 -- value '5' for "other_data" 
FROM (
    SELECT array_agg(first_table_id) AS first_table_ids 
    FROM rows 
) AS rows_as_array 
RETURNING second_table_id 
+0

嘿pozs,这正是我一直在寻找!但是,是否可以在第二个INSERT(而不是'DEFAULT')中包含其他值?例如,我想这样做:'INSERT INTO translations(source_id,destination_id,other_data)SELECT min(phrase_id),max(phrase_id)FROM rows,5',其中'other_data'具有实际值(此处为'5' )。尽管获取语法错误。这是否有正确的语法? – 2015-02-09 16:29:57

+0

@ChrisCirefice是的,你只需要在select中包含它作为一个常量列,看看我的编辑。 – pozs 2015-02-09 16:30:44

+0

这绝对是完美的,正是我昨晚花了两个小时试图找出正确的语法!谢谢:)我确实使用'serial'作为第一个表的列名,所以'min' /'max'解决方案简单得多,符合我的用例。由于在SO上没有类似的问题(无论如何我都能找到),所以我希望你能得到很多赞扬:)再次感谢! – 2015-02-09 16:33:20