I am using a trigger function to write data into a new table in Postgresql 9.1. Everything is now working correctly but I am getting duplicates. Can I use foreign key constraints to prevent duplicates from being produced? I haven`t used foreign key constraints before.
Here is the table structure
DROP TABLE "obx" CASCADE;
CREATE TABLE "obx" (
"obxID" serial primary key,
"Pid" varchar,
"Sid" varchar,
"SidOrig" varchar,
"Parameter" varchar,
"Result" varchar,
"ResultOrig" varchar,
"Units" varchar,
"RefRange" varchar,
"Flag" varchar,
"FlagOrig" varchar,
"OperatorID" varchar,
"ObsTime" char(14),
"MsgTime" char(14),
"UnixTime" int4,
"Analyzer" varchar,
"Segment" varchar
);
DROP TABLE "testcode" CASCADE;
CREATE TABLE "testcode" (
"TcodeID" serial primary key,
"Analyzer" varchar,
"Parameter" varchar,
"TestName" varchar,
"ShortTestName" varchar,
"TestID" int4
) ;
DROP TABLE "finaldata" CASCADE;
CREATE TABLE "finaldata" (
"FdataID" serial primary key,
"Pid" varchar,
"Sid" varchar,
"SidOrig" varchar,
"Parameter" varchar,
"Result" varchar,
"ResultOrig" varchar,
"Units" varchar,
"OperatorID" varchar,
"ObsTime" varchar,
"MsgTime" varchar,
"Analyzer" varchar,
"TestName" varchar,
"ShortTestName" varchar,
"TestID" varchar,
"XYchar1" varchar,
"XYchar2" varchar,
"XYchar3" varchar,
"XYint1" int4,
"XYint2" int4,
"XYint3" int4,
"XYGuid" uuid
) ;
And the trigger function:
BEGIN
INSERT INTO finaldata ("Pid", "Sid", "SidOrig", "Parameter", "Result", "ResultOrig", "Units"
, "OperatorID", "ObsTime", "MsgTime", "Analyzer", "TestName", "ShortTestName", "TestID")
SELECT ob."Pid", ob."Sid", ob."SidOrig", ob."Parameter", ob."Result", ob."ResultOrig", ob."Units"
, ob."OperatorID", ob."ObsTime", ob."MsgTime", ob."Analyzer"
, tc."TestName", tc."ShortTestName", tc."TestID"
FROM obx ob
JOIN testcode tc ON ob."Parameter" = tc."Parameter"
WHERE ob."Sid" = NEW."Sid"
AND ob."ObsTime" = NEW."ObsTime"
AND ob."Parameter" = NEW."Parameter"
AND ob."Analyzer" = NEW."Analyzer"
AND tc."TestID" IS NOT NULL
;
RETURN NEW;
END;
About duplicates
No, you use either
PRIMARY KEYorNOT NULL UNIQUEto prevent duplicates. This declarationguarantees that each row will be unique, but it doesn’t guarantee that the thing the row represents–which is what database designers are interested in–will be unique. Let me give you a smaller example.
The serial ID number makes each row unique, but it doesn’t do anything for the thing the row represents. If I did this
then this insert will succeed,
but running it a second time will fail with this error.
So to prevent duplicates in the table finaldata, you need a UNIQUE constraint on some subset of the columns.
My guess–and it’s just a guess–is that you need at least {“Pid”, “Sid”, “SidOrig”, “Parameter”}.
About foreign keys
Foreign keys guarantee that the values you put in one set of columns already exist in a different table.
For example, the values in the column finaldata.pid probably already exist in another table. If the set of values in the finaldata columns {“Pid”, “Sid”, “SidOrig”, “Parameter”} are supposed to already exist in the table obx, then a foreign key constraint like this will prevent meaningless data from finding its way into those finaldata columns.
You might also need
on delete cascade,on update cascade, or some other referential action.A foreign key will only work if there’s a unique constraint on the referenced columns. You don’t have one of those yet. You’d need a unique constraint on the obx columns {“Pid”, “Sid”, “SidOrig”, “Parameter”} for that specific foreign key constraint to work.