Postgresql
從 SELECT 中插入並結合單個值
我有這個查詢返回幾行
item_id
:select item_id from properties where name like 'body';
我有第二個返回 1 行
tag_id
:select id from tags where name ilike '%hoax%';
我想使用這兩個結果在第三個表中創建新行,
item_tags
以便我可以將item_id
第一個查詢中的每一個插入tag_id
第二個查詢中。我會有類似的東西:
INSERT INTO item_tags (item_id, tag_id) VALUES (item_id1, tag_id); INSERT INTO item_tags (item_id, tag_id) VALUES (item_id2, tag_id); INSERT INTO item_tags (item_id, tag_id) VALUES (item_id3, tag_id); ...
第一個查詢返回 800 多行。如何自動化插入?
psql 9.1.11,Postgres 9.1.4。
基本的
INSERT
INSERT INTO item_tags (item_id, tag_id) SELECT p.item_id, t.id FROM (SELECT item_id FROM properties WHERE name LIKE 'body') p , (SELECT id FROM tags WHERE name ILIKE '%hoax%') t
FROM 子句中的逗號 (
,
) 是 . 的簡寫CROSS JOIN
。這是建立在您的斷言之上的,即第二個查詢
tags
…返回 1 行
tag_id
您從 a 獲得笛卡爾積
CROSS JOIN
,即 n*m 組合。如果連接的兩邊返回多於一行,則它們相乘。
如果任一方均未返回行,則總體結果為無行且沒有任何反應。如果您不想要
這些效果,則一側必須返回至少一行,而另一側必須返回一行。
對於您的特定組合,您還可以使用嵌套子選擇:
INSERT INTO item_tags (item_id, tag_id) SELECT item_id , (SELECT id FROM tags WHERE name ILIKE '%hoax%') AS tag_id -- single result! FROM properties WHERE name LIKE 'body';
***細微的差別:*這會插入從 external 返回的所有行
SELECT
,即使 subselect ontags
沒有返回任何行,這將被轉換為NULL
**fortag_id
。塊
INSERT
要一次處理大量此類插入,您將使用經過大量修改的查詢。但與上述第一個查詢相同的規則適用於兩個連接表中的基數。
INSERT INTO item_tags (item_id, tag_id) SELECT p.item_id, t.id FROM ( VALUES ('body', 'hoax') , ('body2', 'fun') , ('body3', 'love') ) AS it(item, tag) JOIN properties p ON p.name LIKE it.item JOIN tags t ON t.name ILIKE ('%' || it.tag ||'%');
你明白其中的邏輯吧?就個人而言,我稱之為“
CROSS JOIN
代理”。