2012-03-19 90 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