2012-03-19 110 views
0

我正在使用觸發器函數將數據寫入Postgresql 9.1中的新表。一切都在正常工作,但我得到重複。我可以使用外鍵約束來防止重複產生嗎?我之前沒有使用外鍵約束。postgresql外鍵約束,以防止重複

這裏是表結構

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 
    ) ; 

和觸發功能:

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; 

回答

5

我可以使用外鍵約束,以防止重複被生產出來的?

關於重複

不,您使用PRIMARY KEYNOT NULL UNIQUE以防止重複。該聲明

CREATE TABLE "finaldata" (
    "FdataID" serial primary key, 

保證每一排將是唯一的,但不保證該行表示的東西 - 這就是數據庫設計人員感興趣的是 - 將是獨一無二的。讓我給你一個小例子。

create table person (
    person_id serial primary key, 
    full_name varchar(35) not null 
); 

insert into person (full_name) values ('Mendez, Cathy'); 
insert into person (full_name) values ('Mendez, Cathy'); 
insert into person (full_name) values ('Mendez, Cathy'); 
insert into person (full_name) values ('Mendez, Cathy'); 
insert into person (full_name) values ('Mendez, Cathy'); 

select * from person; 
-- 
1 Mendez, Cathy 
2 Mendez, Cathy 
3 Mendez, Cathy 
4 Mendez, Cathy 
5 Mendez, Cathy 

序列ID號,使每個唯一的,但它不會做該行代表的東西什麼。如果我這樣做

delete from person; 
alter table person 
add constraint person_uniq unique (full_name); 

那麼這個插入會成功,

insert into person (full_name) values ('Mendez, Cathy'); 

但運行它第二次會失敗,此錯誤。

ERROR: duplicate key value violates unique constraint "person_uniq" 
SQL state: 23505 
Detail: Key (full_name)=(Mendez, Cathy) already exists. 

因此,爲了防止表finaldata中出現重複,您需要對某些列的子集使用UNIQUE約束。我的猜測 - 這只是一個猜測 - 是你至少需要{「Pid」,「Sid」,「SidOrig」,「Parameter」}。

關於外鍵

外鍵保證你把一組列的值在不同的表已經存在

例如,finaldata.pid列中的值可能已經存在於另一個表中。如果最終數據列{「Pid」,「Sid」,「SidOrig」,「Parameter」}中的值集合應該已經存在於表obx中,那麼像這樣的外鍵約束將阻止無意義的數據找到它進入那些finaldata列。

constraint finaldata_fk1 
foreign key ("Pid", "Sid", "SidOrig", "Parameter") 
    references obx ("Pid", "Sid", "SidOrig", "Parameter") 

您可能還需要on delete cascadeon update cascade,或者一些其他的參考作用。

只有在引用的列上存在唯一約束時,外鍵纔會起作用。你還沒有其中之一。您需要在obx列{「Pid」,「Sid」,「SidOrig」,「Parameter」}上爲該特定外鍵約束生效。

+0

OP之前曾問過這個問題兩次。根本的問題是他的數據模型是不確定的:最終數據表複製了obx的大部分數據(只有對主鍵的引用就足夠了)甚至「參數」字段也不是候選鍵的一部分,因爲它完全功能上依賴於PK(obx) - >參數。一個獨特的FK(obx.ObxId就足夠了)我休息我的情況。 – wildplasser 2012-03-19 15:01:06

+0

我曾問過一個相關的問題,但那是關於觸發器。觸發器部分正在工作。最終數據表是大量信息的副本,但另一個系統連接到數據庫並通過ODBC從最終數據表中讀取數據。這就是它爲什麼設置的原因。現在只有一些重複,我確定唯一的約束和外鍵將整理其餘的。謝謝 – user1044111 2012-03-19 15:29:21

+0

唯一約束成功阻止重複。不幸的是它也阻止了想要的記錄機器分批發送記錄 - 例如可能有10條記錄。 6是需要的,觸發器可以正確地對它們進行過濾 - 除了生成一些重複項(通常是1或2)。我現在試着在觸發器上使用觸發器,看看它是否有效。感謝您的解釋和@wildplasser早期幫助觸發器。 – user1044111 2012-03-20 12:23:55