2013-11-26 46 views
1
create table abstract_addresses (
    address_id int primary key 
); 

create table phone_numbers (
    phone_number text not null unique 
) inherits (abstract_addresses) ; 

create table contacts (
    name text primary key, 
    address_id int not null references abstract_addresses(address_id) 
); 

insert into phone_numbers values (1, '18005551212'); --works 

select * from abstract_addresses; 

address_id 
1 

select * from phone_numbers; 

address_id phone_number 
1   18005551212 


insert into contacts values ('Neil', 1); --error 

我收到此错误信息:为什么使用继承的外键不起作用?

ERROR: insert or update on table "contacts" violates foreign key constraint "contacts_address_id_fkey" 
SQL state: 23503 
Detail: Key (address_id)=(1) is not present in table "abstract_addresses". 

只是一个坏的用例为PostgreSQL表继承?

+0

电话号码插入的工作原理是因为您没有在phone_number上为abstract_addresses创建外键。 – GriffeyDog

+0

@GriffeyDog,在插入到phone_numbers后,abstract_addresses在其address_id中的值为1。 –

回答

3

每告诫在docs:

继承特性的一个严重的局限性是索引(包括唯一约束)和外键约束只适用于单一的表,而不是他们的子女继承。在外键约束的引用和引用方都是如此。

http://www.postgresql.org/docs/current/static/ddl-inherit.html

做你想做什么:

  1. 只有一个ID创建一个表 - 像你这样。

  2. 请勿使用继承。真的不要。分区日志表很有用;不是为了你在做什么。

  3. 使电话号码标识默认为nextval('abstract_addresses_address_id_seq'),或者序列名称。

  4. phone_numbers中添加一个外键,其中引用了abstract_addresses (address_id)。使其可延迟,最初推迟。

  5. phone_numbers上添加插入后触发器,在需要时在abstract_addresses中插入新行。

  6. 如果合适的话,在phone_numbers添加删除后,触发器,级联删除abstract_addresses - 确保它发生当你从phone_numbers删除的删除,否则受影响的行会报告不正确的值。

这样的话,你必须对需要这样的事情偶尔表使用abstract_address,同时仍然能够有一个硬参考phone_numbers其中,后者是你真正想要的东西。

需要注意的一点是:它不能很好地与ORM搭配使用。