最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Creating a DELETE trigger in Db2 - Stack Overflow

programmeradmin0浏览0评论

I’m trying to create an DELETE trigger to archive old data. I have a sample fiddle at .

I have two source tables: parents and children with a foreign key from children to parents:

CREATE TABLE parents (
    id int NOT NULL PRIMARY KEY,
    name varchar(255)
);
CREATE TABLE children (
    id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    parentid int REFERENCES parents(id) ON DELETE CASCADE,
    data varchar(255)
)

The idea is that when a parent row is deleted I want to concatenate the children data and copy the data into an archive table:

CREATE TABLE archive(
    id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    parentid int,
    parentname varchar(255),
    items varchar(255), --  concatenated child data
    archived date
);

I’ve managed to do this in several other dialects of SQL (PostgreSQL, MSSQL, Oracle, MariaDB) but I’m grinding to a halt with Db2.

Here is what I thought might do the job:

CREATE TRIGGER test_trigger
INSTEAD OF DELETE ON parents
REFERENCING OLD AS oldrow FOR EACH ROW
--  BEGIN ATOMIC
    INSERT INTO archive(parentid, parentname, items, archived)
    WITH cte(id, name, child_items) AS (
        SELECT p.id, p.name, listagg(c.data,';')
        FROM parents AS p JOIN children AS c ON c.parentid=p.id
        WHERE p.id=oldrow.id
        GROUP BY p.id, p.name
    )
    SELECT id, name, child_items, current_date
    FROM cte;
--  END

I’m using an INSTEAD OF DELETE trigger because I want to get data from both tables before they’re deleted, and I haven’t yet included the code to delete the data when I’ve finished.

I’m getting errors which I don’t understand. With the BEGIN and END commented out, I get:

SQL Error [42809]: The statement references an object that identifies an unexpected object type. Object: "DB2INST1.PARENTS". Object type: "TABLE". Expected object type: "UNTYPED VIEW".. SQLCODE=-159, SQLSTATE=42809, DRIVER=4.33.31

whatever that means.

With the BEGIN and END enabled I get:

SQL Error [42601]: An unexpected token "END-OF-STATEMENT" was found following "END". Expected tokens may include: "JOIN <joined_table>".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.33.31

whatever that means.

Maybe I should use a different trigger.

Any ideas on how I can finish this?

Using Db2 v12 LUW in a Docker container.

I’m trying to create an DELETE trigger to archive old data. I have a sample fiddle at https://dbfiddle.uk/H_7B93WK .

I have two source tables: parents and children with a foreign key from children to parents:

CREATE TABLE parents (
    id int NOT NULL PRIMARY KEY,
    name varchar(255)
);
CREATE TABLE children (
    id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    parentid int REFERENCES parents(id) ON DELETE CASCADE,
    data varchar(255)
)

The idea is that when a parent row is deleted I want to concatenate the children data and copy the data into an archive table:

CREATE TABLE archive(
    id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    parentid int,
    parentname varchar(255),
    items varchar(255), --  concatenated child data
    archived date
);

I’ve managed to do this in several other dialects of SQL (PostgreSQL, MSSQL, Oracle, MariaDB) but I’m grinding to a halt with Db2.

Here is what I thought might do the job:

CREATE TRIGGER test_trigger
INSTEAD OF DELETE ON parents
REFERENCING OLD AS oldrow FOR EACH ROW
--  BEGIN ATOMIC
    INSERT INTO archive(parentid, parentname, items, archived)
    WITH cte(id, name, child_items) AS (
        SELECT p.id, p.name, listagg(c.data,';')
        FROM parents AS p JOIN children AS c ON c.parentid=p.id
        WHERE p.id=oldrow.id
        GROUP BY p.id, p.name
    )
    SELECT id, name, child_items, current_date
    FROM cte;
--  END

I’m using an INSTEAD OF DELETE trigger because I want to get data from both tables before they’re deleted, and I haven’t yet included the code to delete the data when I’ve finished.

I’m getting errors which I don’t understand. With the BEGIN and END commented out, I get:

SQL Error [42809]: The statement references an object that identifies an unexpected object type. Object: "DB2INST1.PARENTS". Object type: "TABLE". Expected object type: "UNTYPED VIEW".. SQLCODE=-159, SQLSTATE=42809, DRIVER=4.33.31

whatever that means.

With the BEGIN and END enabled I get:

SQL Error [42601]: An unexpected token "END-OF-STATEMENT" was found following "END". Expected tokens may include: "JOIN <joined_table>".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.33.31

whatever that means.

Maybe I should use a different trigger.

Any ideas on how I can finish this?

Using Db2 v12 LUW in a Docker container.

Share Improve this question edited Mar 19 at 5:44 Manngo asked Mar 19 at 5:19 ManngoManngo 16.6k13 gold badges104 silver badges148 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

INSTEAD OF triggers are used on views in DB2, not on tables.
You may use a compiled (BEGIN ... END, not BEGIN ATOMIC ... END) compound statement in a BEFORE DELETE trigger on the parent table to get the result.
Notice, that you must use different statement terminator (@ here) in your script instead of the default one (;), when the script has a compound statement.

--#SET TERMINATOR @

CREATE TABLE parents (
    id int NOT NULL PRIMARY KEY,
    name varchar(255)
)@

CREATE TABLE children (
    id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    parentid int REFERENCES parents(id) ON DELETE CASCADE,
    data varchar(255)
)
@

CREATE TABLE archive(
    id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    parentid int,
    parentname varchar(255),
    items varchar(255), --  concatenated child data
    archived date
)
@

CREATE TRIGGER test_trigger
BEFORE DELETE ON parents
REFERENCING OLD AS oldrow FOR EACH ROW
BEGIN 
    INSERT INTO archive(parentid, parentname, items, archived)
    WITH cte(id, name, child_items) AS (
        SELECT p.id, p.name, listagg(c.data,';')
        FROM parents AS p JOIN children AS c ON c.parentid=p.id
        WHERE p.id=oldrow.id
        GROUP BY p.id, p.name
    )
    SELECT id, name, child_items, current_date
    FROM cte;
END
@

INSERT INTO parents (id, name) VALUES (1, 'name1')@
INSERT INTO children (parentid, data) VALUES (1, 'data1'), (1, 'data2')@
DELETE from parents@
SELECT * FROM archive@

The result of the last query is:

ID PARENTID PARENTNAME ITEMS ARCHIVED
1 1 name1 data1;data2 2025-03-19

fiddle

发布评论

评论列表(0)

  1. 暂无评论