取消触发器内的插入而不回滚

发布于 2024-09-18 19:44:03 字数 1055 浏览 2 评论 0原文

对于某项作业,我的任务是创建一个非常简单的问答网站,其中包含标记的问题和评论的答案。

要求之一是要有一个触发器来检测重复标签的插入,如果是这种情况,则增加已存在标签的使用计数器。
问题是,我无法通过回滚整个事务(包括 UPDATE)来取消触发器,这违背了触发器的目的。

关于如何实现它有什么想法吗?

更新

要求的措辞如下:

创建触发器来检查数据库中是否先前不存在要添加的任何标签。如果存在,则相应行中的 use 列必须增加 1”
(原文:“创建触发器 tg_insertar_tag que revise que cualquier nuevo tag que se agregue no exita antes en la base de datos; >en caso de excistir, se debe Incrementar en 1 la columna “usos” de la tabla tag del registro que countera")

此要求无法更改或避免,但欢迎出现漏洞。


作为参考,我当前的触发代码:

CREATE OR REPLACE TRIGGER tg_insertar_tag BEFORE INSERT ON Tag
FOR EACH ROW
DECLARE
    tagCount integer;
    v_usos integer;
BEGIN
    SELECT COUNT(*) INTO tagCount FROM Tag WHERE nombre = :new.nombre;
    SELECT Usos INTO v_usos FROM Tag WHERE nombre = :new.nombre;
    IF tagCount > 0 THEN
        UPDATE Tag SET usos = v_usos + 1 WHERE nombre = :new.nombre;
    ELSE
        :new.usos := 1;
    END IF;
END;

For a certain assignment, I'm tasked with creating a very simple Q/A site, complete with tagged questions and commented answers.

One of the requirements is to have a trigger to detect the insertion of duplicate tags and, if such is the case, increment the already-existing tag's usage counter.
Problem is, I can't cancel the trigger with rolling back the entire transaction, including the UPDATE, which defeats the purpose of the trigger.

Any ideas on how to pull it off?

UPDATE

The requirement's phrased like follows:

"Create the trigger that checks if any tag to be added doesn't previously exist in the database. In case it exists, the use column in the corresponding row must be incremented by 1"
(Original language: "Crear el trigger tg_insertar_tag que revise que cualquier nuevo tag que se agregue no exista antes en la base de datos; en caso de existir, se debe incrementar en 1 la columna “usos” de la tabla tag del registro que corresponda")

This requirement can't be changed or avoided, although loopholes would be welcome.


For reference, my current trigger code:

CREATE OR REPLACE TRIGGER tg_insertar_tag BEFORE INSERT ON Tag
FOR EACH ROW
DECLARE
    tagCount integer;
    v_usos integer;
BEGIN
    SELECT COUNT(*) INTO tagCount FROM Tag WHERE nombre = :new.nombre;
    SELECT Usos INTO v_usos FROM Tag WHERE nombre = :new.nombre;
    IF tagCount > 0 THEN
        UPDATE Tag SET usos = v_usos + 1 WHERE nombre = :new.nombre;
    ELSE
        :new.usos := 1;
    END IF;
END;

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

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

发布评论

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

评论(2

〆一缕阳光ご 2024-09-25 19:44:03

这不是表上触发器的用途。

您应该使用来自存储过程、INSTEAD OF 触发器或仅来自客户端的 MERGE 语句:

MERGE
INTO    tag tc
USING   (
        SELECT  :NEW.nombre
        FROM    dual
        ) t
ON      (tc.nombre = t.nombre)
WHEN MATCHED THEN
UPDATE
SET     usos = usos + 1
WHEN NOT MATCHED THEN
INSERT  (nombre, usos)
VALUES  (nombre, 1)

从性能角度来看,最好传递集合中的所有标记从客户端执行此查询:

MERGE
INTO    tag tc
USING   (
        SELECT  tag, COUNT(*) AS cnt
        FROM    TABLE(:mycollection)
        GROUP BY
                nombre
        ) t
ON      (tc.nombre = t.nombre)
WHEN MATCHED THEN
UPDATE
SET     usos = usos + cnt
WHEN NOT MATCHED THEN
INSERT  (nombre, usos)
VALUES  (nombre, cnt)

在存储过程中,该过程将接受集合作为参数。

That's not what the triggers on a table are for.

You should use a MERGE statement from a stored procedure, an INSTEAD OF trigger or just from the client:

MERGE
INTO    tag tc
USING   (
        SELECT  :NEW.nombre
        FROM    dual
        ) t
ON      (tc.nombre = t.nombre)
WHEN MATCHED THEN
UPDATE
SET     usos = usos + 1
WHEN NOT MATCHED THEN
INSERT  (nombre, usos)
VALUES  (nombre, 1)

Performance-wise, it would be best to pass all tags in a collection from the client and perform this query:

MERGE
INTO    tag tc
USING   (
        SELECT  tag, COUNT(*) AS cnt
        FROM    TABLE(:mycollection)
        GROUP BY
                nombre
        ) t
ON      (tc.nombre = t.nombre)
WHEN MATCHED THEN
UPDATE
SET     usos = usos + cnt
WHEN NOT MATCHED THEN
INSERT  (nombre, usos)
VALUES  (nombre, cnt)

in the stored procedure which would accept the collection as a parameter.

放我走吧 2024-09-25 19:44:03

或者...

将这种逻辑放在另一个具有相同或相似结构的表上。

然后,当插入通过时,您可以使用后触发逻辑将其插入主表中。

or...

place this kind of logic on another table with the same or similar structure.

then when the insert passes, you use a post trigger logic to also insert it into the primary table.

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