将Postgres中的外键定义为目标表的子集

时间:2015-09-22 06:31:06

标签: sql postgresql subtyping

例:
我有:

Table A:  
 int id  
 int table_b_id

Table B:  
 int id  
 text type  

我想在列table_b_id上添加一个约束检查,以验证它是否仅指向表B中的行,其类型值为' X'。
我无法改变桌面结构 我已经明白可以通过“检查”来完成这项工作。和postgres函数将进行特定的查询,但我看到人们建议避免它 任何关于实施它的最佳方法的输入都会有所帮助。

2 个答案:

答案 0 :(得分:0)

你所指的不是FOREIGN KEY,它在PostgreSQL中是指另一个表中的(一些)列,其中该列/那些列上有唯一索引(s ),当那些/那些列的值发生变化时,可能会有相关的自动操作(ON UPDATEON DELETE)。

您正在尝试强制执行特定类型的引用完整性,类似于FOREIGN KEY所执行的操作。您可以使用CHECK子句和函数执行此操作(因为CHECK子句不允许子查询),您也可以使用table inheritance and range partitioning执行此操作(请参阅子表,仅保留type = 'X')的行,但使用触发器可能最容易实现:

CREATE FUNCTION trf_test_type_x() RETURNS trigger AS $$
BEGIN
  PERFORM * FROM tableB WHERE id = NEW.table_b_id AND type = 'X';
  IF NOT FOUND THEN
    -- RAISE NOTICE 'Foreign key violation...';
    RETURN NULL;
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE tr_test_type_x
BEFORE INSERT OR UPDATE ON tableA
FOR EACH ROW EXECUTE PROCEDURE trf_test_type_x();

您可以在tableB上创建部分索引以加快速度:

CREATE UNIQUE INDEX idx_type_X ON tableB(id) WHERE type = 'X';

答案 1 :(得分:0)

在我看来,最优雅的解决方案是使用inheritance来获取子类型行为:

PostgreSQL 9.3 Schema Setup with inheritance:

create table B ( id int primary key );

-- Instead to create a 'type' field, inherit from B for
-- each type with custom properties:
create table B_X ( -- some_data varchar(10 ),
                   constraint pk primary key (id)
                 ) inherits (B);

-- Sample data:
insert into B_X (id) values ( 1 );
insert into B (id)   values ( 2 );

-- Now, instead to reference B, you should reference B_X:
create table A ( id int primary key, B_id int references B_X(id) );

-- Here it is:
insert into A values ( 1, 1 );

--Inserting wrong values will causes violation:
insert into A values ( 2, 2 );    
  

错误:在表格上插入或更新" a"违反外键约束" a_b_id_fkey"    细节:表格中没有键(b_id)=(2)" b_x"。

从基表中检索所有数据

select * from B

<强> Results

| id |
|----|
|  2 |
|  1 |

检索类型为的数据:

SELECT p.relname, c.*
FROM B c inner join pg_class p on c.tableoid = p.oid

<强> Results

| relname | id |
|---------|----|
|       b |  2 |
|     b_x |  1 |