我希望能够跟踪表格中相关记录的历史记录。在Oracle系统上,我通过创建一个插入触发器来完成此操作,该触发器将使用原始记录的PK(如果已知)填充字段,或者如果未指定原始PK则使用新PK填充。
换句话说,给定以下代码,INS_Nomination触发器将使用传入的parent_nomination_id填充新的Nomination.parent_nomination_id字段,或者如果parent_nomination_id为NULL,则填充为表的PK(nomination_id)生成的值:
/*create nomination tables*/
CREATE TABLE Nomination (
nomination_id NUMBER(12,0) NOT NULL ENABLE,
parent_nomination_id NUMBER(12,0) NOT NULL,
whatever VARCHAR2(400 BYTE),
created_by NUMBER(12,0) NOT NULL ENABLE,
created_date DATE DEFAULT SYSDATE NOT NULL ENABLE,
active_ind NUMBER(1,0) DEFAULT 1 NOT NULL ENABLE,
CONSTRAINT Nomination_PK PRIMARY KEY (nomination_id) ENABLE
);
CREATE INDEX Nomination_INDEX1 ON Nomination (parent_nomination_id, active_ind DESC) ;
CREATE UNIQUE INDEX Nomination_PK ON Nomination (nomination_id);
CREATE SEQUENCE Nomination_SEQ;
CREATE OR REPLACE TRIGGER INS_Nomination BEFORE INSERT ON Nomination FOR EACH ROW
BEGIN
SELECT Nomination_SEQ.nextval
INTO :new.nomination_id
FROM Dual;
SELECT NVL(:NEW.parent_nomination_id, :NEW.nomination_id)
INTO :NEW.parent_nomination_id
FROM Dual;
END;
/
ALTER TRIGGER INS_Nomination ENABLE;
如何使用Postgres完成相同的功能?
答案 0 :(得分:2)
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;
CREATE TABLE nomination
( nomination_id BIGSERIAL NOT NULL PRIMARY KEY
, parent_nomination_id BIGINT NOT NULL
REFERENCES nomination(nomination_id)
, whatever VARCHAR
, created_by INTEGER NOT NULL DEFAULT 0
, created_date DATE NOT NULL DEFAULT CURRENT_DATE
, active_ind boolean NOT NULL DEFAULT true
);
CREATE OR REPLACE FUNCTION nomination_fix_parent() RETURNS TRIGGER
AS
$func$
BEGIN
NEW.parent_nomination_id := NEW.nomination_id ;
RETURN NEW;
END
$func$ LANGUAGE plpgsql ;
CREATE TRIGGER nomination_fix_parent
BEFORE INSERT ON nomination
FOR EACH ROW
WHEN (NEW.parent_nomination_id IS NULL)
EXECUTE PROCEDURE nomination_fix_parent()
;
-- Test it ...
INSERT INTO nomination(whatever) VALUES('First?' );
INSERT INTO nomination(parent_nomination_id, whatever) VALUES(1,'Second?' );
INSERT INTO nomination(nomination_id, parent_nomination_id, whatever) VALUES(5,1,'Five?' );
SELECT * FROM nomination;
-- after entering the third record with id=5, the sequence is out of sequence ...
SELECT currval('nomination_nomination_id_seq');
-- Re-adjust the value for the sequence
SELECT setval('nomination_nomination_id_seq', (SELECT MAX(nomination_id) FROM nomination) );
INSERT INTO nomination(whatever) VALUES('Fourth?' );
SELECT * FROM nomination;
注意:
PRIMARY KEY
和REFERENCES
子句会自动为您创建索引SERIAL
和BIGSERIAL
自动创建序列,并将其nextval()用作默认值DEFAULT
,而不是基于序列,而是在同一行的nomination_id上(可能是基于序列)。setval('nomination_id_seq', select max() from ...)
)。