mam*_*aye 10 postgresql insert postgresql-9.1
我有这个查询返回几行item_id:
select item_id from properties where name like 'body';
Run Code Online (Sandbox Code Playgroud)
我有第二个返回 1 行的tag_id:
select id from tags where name ilike '%hoax%';
Run Code Online (Sandbox Code Playgroud)
我想使用这两个结果在第三个表中创建新行,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);
...
Run Code Online (Sandbox Code Playgroud)
第一个查询返回超过 800 行。如何自动化插入?
psql 9.1.11,Postgres 9.1.4。
Erw*_*ter 11
INSERTINSERT 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
Run Code Online (Sandbox Code Playgroud)
其中,,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';
Run Code Online (Sandbox Code Playgroud)
细微的差别:这会插入从外部返回的所有行SELECT,即使子选择tags没有返回任何行,这将被转换为NULLfortag_id。
INSERT要一次处理大量此类插入,您将使用经过大量修改的 query。但是与上面第一个查询相同的规则适用于两个连接表中的基数。
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 ||'%');
Run Code Online (Sandbox Code Playgroud)
你看逻辑对不对?就个人而言,我称之为“CROSS JOIN代理”。