跨表强制执行约束的最佳方法是什么?

时间:2015-06-09 01:39:03

标签: sql postgresql

我经常发现自己遇到了像这样的情况(这是人为的,但说明了问题):

CREATE TABLE customer (
  id   SERIAL PRIMARY KEY,
  type TEXT
  -- other columns...
);

CREATE TABLE product_order (
  id          SERIAL PRIMARY KEY,
  customer_id INTEGER REFERENCES customer (id),
  type        TEXT REFERENCES customer (type), -- not actually legitimate
  -- other columns...
  CHECK (type = 'business')
);

当然,product_order.type上的外键约束不起作用,因为customer.type不是UNIQUE或主键(我不能使用CHECK CONSTRAINT在仅存在于另一个表中的列上)。但是,我只希望product_order客户type = 'business'条目。

我可以将customer.idcustomer.type作为复合主键,但是那些只想引用customer.id的其他表也必须不必要地引用customer.type

在这种情况下,最好的方法是什么?

编辑:忘记外键约束product_order.customer_id

4 个答案:

答案 0 :(得分:2)

您可以为类型创建查找表,并使用FKEY关系强制执行

CREATE TABLE type (
  id   integer, PRIMARY KEY,
  name TEXT
);

CREATE TABLE customer (
  id   SERIAL PRIMARY KEY,
  type_id INTEGER, NOT NULL
  -- other columns...
  FOREIGN KEY (type_id) REFERENCES type(id)
);

CREATE TABLE product_order (
  id   SERIAL PRIMARY KEY,
  type_id INTEGER, NOT NULL
  -- other columns...
  FOREIGN KEY (type_id) REFERENCES type(id)
);

答案 1 :(得分:2)

如果您在customer.type上创建了唯一的约束,则可以从product_order表中引用它:

CREATE TABLE customer (
  id   SERIAL PRIMARY KEY,
  type TEXT,
  -- other columns...
  constraint unique_cust_type unique (id, type) -- this makes the combination id/type "referencable"
);


CREATE TABLE product_order 
(
  id          SERIAL PRIMARY KEY,
  customer_id INTEGER,
  type        TEXT default 'business',
  CHECK (type = 'business'),
  foreign key (customer_id, type) references customer (id, type)
);

答案 2 :(得分:0)

您可以访问product_order作为视图:

create view product_order_vw
as
select po.* 
from product_order po
join customer c
on c.customerid = po.customerid
where c.type = 'business'

答案 3 :(得分:0)

我认为你需要另一种类型。此示例采用MS SQL格式:

    CREATE TABLE TYPES (ctype varchar(10) NOT NULL PRIMARY KEY,
         name varchar(50) not null
    );

    CREATE TABLE product_order (
           id   SERIAL PRIMARY KEY,
           type varchar(10) NOT NULL REFERENCE TYPES (ctype) , 
           ....
    );

因此,您的product_order必须在Types表中定义类型。在您的示例中,您只有一个条目“业务”,但您可以根据需要添加任意数量。