From: | Jason Aleski <jason(dot)aleski(at)gmail(dot)com> |
---|---|
To: | pgsql-sql(at)lists(dot)postgresql(dot)org |
Subject: | Trouble with single trigger using UUID as key, should I use two triggers? |
Date: | 2018-03-10 02:15:47 |
Message-ID: | 456d6fa7-0ade-4ceb-195b-77c37818c02f@gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-sql |
I'm running into a foreign key constraint when running a BEFORE trigger
for audit purposes. My initial goal was to do this in one BEFORE
trigger, but I'm leaning towards executing using two different
triggers. I'm seeking a second opinion! My initial thought was
creating a trigger that runs before the data is written to the primary
table; specifically on updates, as I want to increment the version_count
before the data is written to the primary table. Because the audit_id
(UUID generated) has not been written to the primary table, I get a
foreign key constraint problem when it tries to first write to the audit
table. I understand the error is because audit_id doesn't exist in the
primary table. If I were using a SERIAL/SEQUENCE, I could use the
NEXTVAL function; but I need to use UUID the key and audit_id.
Knowing that, I think my only option is to create an AFTER trigger for
the INSERT. Then create a BEFORE trigger when doing UPDATES and
DELETES. Before I go this path, I through I'd see if anyone has any
additional options I should consider; or would this be the suggested
path? Thoughts?
-JA-
--Example INSERT
INSERT INTO departments (department_legacyid, department_name) VALUES
('ACT', 'Accounting');
INSERT INTO departments (department_legacyid, department_name) VALUES
('HRM', 'Human Resources');
INSERT INTO departments (department_legacyid, department_name) VALUES
('CSR', 'Customer Service');
--ERROR
ERROR: insert or update on table "departments_audit" violates foreign
key constraint "departments_audit_audit_id_fkey" DETAIL: Key
(audit_id)=(241451bd-796e-5add-95b0-18f6098bc08f) is not present in
table "departments". CONTEXT: SQL statement "INSERT INTO
departments_audit (audit_id, audit_lastaction, department_legacyid,
department_name ) VALUES (NEW.audit_id, 'INSERT',
NEW.department_legacyid, NEW.department_name )" PL/pgSQL function
process_departments_audit() line 10 at SQL statement SQL state: 23503
--Primary Table
CREATE TABLE IF NOT EXISTS departments (
row_id UUID NOT NULL DEFAULT
uuid_generate_v5(uuid_ns_dns(), 'location1.local'),
row_created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT
CURRENT_TIMESTAMP,
audit_id UUID NOT NULL DEFAULT
uuid_generate_v5(uuid_ns_dns(), 'location1.local'),
version_count INTEGER NOT NULL DEFAULT 1,
version_timestamp TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT
CURRENT_TIMESTAMP,
department_legacyid VARCHAR(255) NOT NULL,
department_name VARCHAR(255) NOT NULL,
PRIMARY KEY (row_id)
);
--Creating index on audit_ID to ensure there is only one unique record
in primary table
CREATE UNIQUE INDEX departments_ref_idx ON departments(audit_id);
--Audit Table
CREATE TABLE IF NOT EXISTS departments_audit (
row_id UUID NOT NULL DEFAULT
uuid_generate_v5(uuid_ns_dns(), 'location1.local'),
row_created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT
CURRENT_TIMESTAMP,
audit_id UUID NOT NULL DEFAULT
uuid_generate_v5(uuid_ns_dns(), 'location1.local'),
audit_lastaction CHARACTER VARYING DEFAULT 'NOT DEFINED',
version_count INTEGER NOT NULL DEFAULT 1,
version_timestamp TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT
CURRENT_TIMESTAMP,
department_legacyid VARCHAR(255) NOT NULL,
department_name VARCHAR(255) NOT NULL,
PRIMARY KEY (row_id),
FOREIGN KEY (audit_id) REFERENCES departments(audit_id)
);
-- Creating audit trigger for departments
CREATE OR REPLACE FUNCTION process_departments_audit() RETURNS TRIGGER
AS $departments_audit$
BEGIN
IF (TG_OP = 'DELETE') THEN
--Nothing yet
ELSEIF (TG_OP = 'UPDATE') THEN
--Nothing yet
NEW.version_count = OLD.version_count + 1;
ELSEIF (TG_OP = 'INSERT') THEN
INSERT INTO departments_audit (audit_id,
audit_lastaction,
department_legacyid,
department_name
)
VALUES (NEW.audit_id,
'INSERT',
NEW.department_legacyid,
NEW.department_name
);
END IF;
RETURN NULL;
END;
$departments_audit$ LANGUAGE plpgsql;
--Applying trigger BEFORE data is written to primary table
CREATE TRIGGER department_audit
BEFORE INSERT OR UPDATE OR DELETE ON departments
FOR EACH ROW EXECUTE PROCEDURE process_departments_audit();
From | Date | Subject | |
---|---|---|---|
Next Message | abctevez | 2018-03-16 13:42:20 | does the notification of postgres appear in transaction completed order |
Previous Message | Stanton Schmidt | 2018-03-08 20:17:58 | Re: Query question |