使用相同的外键插入多个值

Insert multiple values with the same foreign key

我有两个相互引用的表:

CREATE TABLE Room
    room_id INTEGER PRIMARY KEY,
    room_name TEXT UNIQUE NOT NULL;

CREATE TABLE Item
    item_id INTEGER PRIMARY KEY,
    room_id INTEGER,
    item_name TEXT,
    FOREIGN KEY (room_id) REFERENCES Room (room_id) ON UPDATE RESTRICT ON DELETE RESTRICT;

现在我想添加一个新房间,添加几十个项目进去。

INSERT INTO Room(room_name) VALUES ('Living Room');

假设我不知道有多少个房间,我只想把东西放到客厅里。为此,我需要 select 正确 room_id。对于单个项目来说,这还算不错:

INSERT INTO Item(room_id, item_name)
    SELECT room_id, 'Couch' AS item_name FROM Room WHERE room_name = 'Living Room';

但是如果我想同时插入一堆值怎么办。我尝试使用 last_insert_rowid,但这并没有将整个 INSERT 视为单个事务。也就是说,最后一个ID一直递增

INSERT INTO Item (room_id, item_name)
  VALUES
    (last_insert_rowid(), 'Chair'),
    (last_insert_rowid(), 'TV'),
    (last_insert_rowid(), 'Carpet');

我想避免在每个新行上都使用 SELECT。有没有办法在 Item 中插入多个值,同时在 Room 中引用最后一个已知的 room_id

CROSS JOIN 性质的东西可能非常有用,但我不知道如何让常量在这种情况下表现

我要寻找的最终结果是 Room 看起来像这样:

room_id | room_name
--------+-----------
      1 | Living Room

Item 像这样:

item_id | room_id | item_name
--------+---------+-----------
      1 |       1 | Chair
      2 |       1 | TV
      3 |       1 | Carpet

您可以使用从新房间获得的 ID 的 CROSS 连接到 CTE,returns 您要插入的项目:

WITH cte(item_name) AS (VALUES ('Chair'), ('TV'), ('Carpet'))
INSERT INTO Item (room_id, item_name)
SELECT r.room_id, c.item_name
FROM Room r CROSS JOIN cte c
WHERE r.room_name = 'Living Room';

参见demo

如果您使用的 SQLite 版本不支持 CTE,请在子查询中使用 UNION ALL

INSERT INTO Item (room_id, item_name)
SELECT r.room_id, c.item_name
FROM Room r 
CROSS JOIN (
  SELECT 'Chair' item_name UNION ALL 
  SELECT 'TV' UNION ALL
  SELECT 'Carpet'
) c
WHERE r.room_name = 'Living Room';

参见demo