用相同的外键插入多个值

发布于 2025-01-20 05:29:09 字数 1428 浏览 3 评论 0原文

我有两个互相参考的表格:

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');

假设我不知道有多少个房间,我只想把东西放入客厅。为此,我需要选择正确的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,但这不会将整个插入视为单个交易。换句话说,最后一个ID一直在增加,

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

我想避免在每个新行上使用选择。是否有一种方法可以将多个值插入item,同时引用Room中的最后一个已知ROOM_ID

交叉加入的性质中的某些内容可能非常有用,但是我不知道如何使常数在这种情况下以

最终结果为例。 看起来像这样:

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

item这样:

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

I have two tables that reference each other:

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;

Now I want to add a new room and add a few dozen items to go into it.

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

Let's say I don't know how many rooms there are, and I just want to put stuff into the living room. To do that, I need to select the right room_id. For a single item this is not too bad:

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

But what if I want to insert a bunch of values simultaneously. I tried using last_insert_rowid, but that does not treat the entire INSERT as a single transaction. In other words, the last ID keeps incrementing

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

I would like to avoid having to use the SELECT on each new row. Is there a way to insert multiple values into Item, while referencing the last known room_id in Room?

Something in the nature of a CROSS JOIN would likely be very useful, but I don't know how to get the constants to behave in that case

The end result I am looking for is for Room to look like this:

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

And Item like this:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烟织青萝梦 2025-01-27 05:29:09

您可以使用从新房间获得的 id 的 CROSS 连接到返回要插入的项目的 CTE:

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';

请参阅 演示

如果您使用的 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';

请参阅 演示

You can use a CROSS join of the id that you get from the new room to a CTE that returns the items that you want to insert:

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';

See the demo.

If you are using a version of SQLite that does not support CTEs use UNION ALL in a subquery:

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';

See the demo.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文