当行被 FK 引用时执行 UPSERT

发布于 2024-10-31 11:00:00 字数 1235 浏览 1 评论 0原文

假设我有一个项目表,对于每个项目,可以为其存储附加信息,这些信息会进入第二个表。附加信息由第一个表中的 FK 引用,该 FK 可以为 NULL(如果该项目没有附加信息)。

TABLE item (
    ...
    item_addtl_info_id INTEGER
)

CONSTRAINT fk_item_addtl_info FOREIGN KEY (item_addtl_info)
    REFERENCES addtl_info (addtl_info_id)

TABLE addtl_info (
    addtl_info_id INTEGER NOT NULL
    GENERATED BY DEFAULT 
    AS IDENTITY (
        INCREMENT BY 1
        NO CACHE
        ),
    addtl_info_text VARCHAR(100)
    ...
    CONSTRAINT pk_addtl_info PRIMARY KEY (addtl_info_id)
)

更新项目附加信息的“最佳实践”是什么(最好是在 IBM DB2 SQL 中)?

它应该是一个 UPSERT 操作,这意味着如果附加信息尚不存在,则在第二个表中创建一条新记录,但如果存在,则仅更新它,第一个表中的 FK 不会更改。

因此,这就是逻辑:

UPSERT(item, item_info):
CASE WHEN item.item_addtl_info_id IS NULL THEN
    INSERT INTO addtl_info (item_info)
    UPDATE item.item_addtl_info_id (addtl_info.addtl_info_id)
                                               ^^^^^^^^^^^^^
ELSE
    UPDATE addtl_info (item_info)
END

我的主要问题是如何获取新插入的 addtl_info 行的 id(上面下划线)。在存储过程中,我可以从序列中请求 id 并将其存储在变量中,但也许有更直接的方法。这不是在数据库编程时经常出现的问题吗?

我的意思是,我真的对 addtl_info 记录的 id 不感兴趣,只要它保持唯一并且被正确引用即可。因此,在这种情况下,使用序列对我来说似乎有点矫枉过正。

事实上,这个 UPSERT 操作应该是 SQL 语言的一部分作为标准操作(也许是,但我只是不知道?)...

Let's say that I have a table of items, and for each item, there can be additional information stored for it, which goes into a second table. The additional information is referenced by a FK in the first table, which can be NULL (if the item doesn't have additional info).

TABLE item (
    ...
    item_addtl_info_id INTEGER
)

CONSTRAINT fk_item_addtl_info FOREIGN KEY (item_addtl_info)
    REFERENCES addtl_info (addtl_info_id)

TABLE addtl_info (
    addtl_info_id INTEGER NOT NULL
    GENERATED BY DEFAULT 
    AS IDENTITY (
        INCREMENT BY 1
        NO CACHE
        ),
    addtl_info_text VARCHAR(100)
    ...
    CONSTRAINT pk_addtl_info PRIMARY KEY (addtl_info_id)
)

What is the "best practice" to update an item's additional info (in IBM DB2 SQL, preferably)?

It should be an UPSERT operation, meaning that if additional info does not yet exist then a new record is created in the second table, but if it does, then it is only updated, and the FK in the first table does not change.

So imperatively, this is the logic:

UPSERT(item, item_info):
CASE WHEN item.item_addtl_info_id IS NULL THEN
    INSERT INTO addtl_info (item_info)
    UPDATE item.item_addtl_info_id (addtl_info.addtl_info_id)
                                               ^^^^^^^^^^^^^
ELSE
    UPDATE addtl_info (item_info)
END

My main problem is how to get the newly inserted addtl_info row's id (underlined above). In a stored proc I can request the id from a sequence and store it in a variable, but maybe there is a more straightforward way. Isn't it something that comes up all the time when programming databases?

I mean, I'm really not interested in what the id of the addtl_info record is as long as it remains unique and is referenced properly. So using sequences seems a bit of an overkill to me in this case.

As a matter of fact, this UPSERT operation should be part of the SQL language as a standard operation (maybe it is, and I just don't know about it?)...

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

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

发布评论

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

评论(1

書生途 2024-11-07 11:00:00

我正在寻找的语法是:

SELECT * FROM NEW TABLE ( INSERT INTO phone_book VALUES ( 'Peter Doe','555-2323' ) )

来自维基百科(http://en.wikipedia.org/ wiki/Insert_%28SQL%29)

这是如何引用刚刚插入表中的记录。

我的同事将此构造称为“就地触发器”,它的真正含义是...

这是我作为复合 SQL 语句组合在一起的第一个版本:

begin atomic
declare addtl_id integer;
set addtl_id = (select item_addtl_info_id from item where item.item_id = XXX);
if addtl_id is null
then
    set addtl_id = (select addtl_info_id from new table 
                    (insert into addtl_info
                        (addtl_info_text)
                        values ('My brand new additional info')
                    )
                  );
    update item set item.item_addtl_info_id = addtl_id
    where item.item_id = XXX;

else
   update addtl_info set addtl_info_text = 'My updated additional info'
   where addtl_info.addtl_info_id = addtl_id;
end if;
end

XXX 等于项目 id待更新 - 现在可以轻松地将代码插入到存储过程中,并且可以将 XXX 转换为输入参数。

我还尝试使用 MERGE INTO,但我无法找出用于更新与指定目标不同的表的语法。

The syntax I was looking for is:

SELECT * FROM NEW TABLE ( INSERT INTO phone_book VALUES ( 'Peter Doe','555-2323' ) )

from Wikipedia (http://en.wikipedia.org/wiki/Insert_%28SQL%29)

This is how to refer to the record that was just inserted in the table.

My colleague called this construct an "in-place trigger", which what it really is...

Here is the first version that I put together as a compound SQL statement:

begin atomic
declare addtl_id integer;
set addtl_id = (select item_addtl_info_id from item where item.item_id = XXX);
if addtl_id is null
then
    set addtl_id = (select addtl_info_id from new table 
                    (insert into addtl_info
                        (addtl_info_text)
                        values ('My brand new additional info')
                    )
                  );
    update item set item.item_addtl_info_id = addtl_id
    where item.item_id = XXX;

else
   update addtl_info set addtl_info_text = 'My updated additional info'
   where addtl_info.addtl_info_id = addtl_id;
end if;
end

XXX being equal to the item id to be updated - this code can now be easily inserted into a sproc, and XXX can be converted to an input parameter.

I also tried using MERGE INTO, but I couldn't figure out a syntax for updating a table different from what was specified as the target.

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