[英]how to create a Foreign-Key constraint to a subset of the rows of a table?
I have a reference table, say OrderType
that collects different types of orders: 我有一个参考表,比如
OrderType
,它收集不同类型的订单:
CREATE TABLE IF NOT EXISTS OrderType (name VARCHAR);
ALTER TABLE OrderType ADD PRIMARY KEY (name);
INSERT INTO OrderType(name) VALUES('sale-order-type-1');
INSERT INTO OrderType(name) VALUES('sale-order-type-2');
INSERT INTO OrderType(name) VALUES('buy-order-type-1');
INSERT INTO OrderType(name) VALUES('buy-order-type-2');
I wish to create a FK constraint from another table, say SaleInformation
, pointing to that table ( OrderType
). 我希望从另一个表创建一个FK约束,比如
SaleInformation
,指向该表( OrderType
)。 However, I am trying to express that not all rows of OrderType
are eligible for the purposes of that FK (it should only be sale-related order types). 但是,我试图表示并非所有
OrderType
符合FK的目的(它应该只是与销售相关的订单类型)。
I thought about creating a view of table OrderType
with just the right kind of rows (view SaleOrderType
) and adding a FK constraint to that view, but PostgreSQL balks at that with: 我想到创建一个表
OrderType
的视图,只有正确的行(查看SaleOrderType
)并向该视图添加一个FK约束,但PostgreSQL在那里使用:
ERROR: referenced relation "SaleOrderType" is not a table
So it seems I am unable to create a FK constraint to a view (why?). 所以我似乎无法为视图创建FK约束(为什么?)。 Am I only left with the option of creating a redundant table to hold the sale-related order types?
我是否只选择创建一个冗余表来保存与销售相关的订单类型? The alternative would be to simply allow the FK to point to the original table, but then I am not really expressing the constraint as strictly as I would like to.
另一种方法是简单地允许FK指向原始表,但是我并没有像我想的那样严格地表达约束。
I think your schema should be something like this 我认为你的架构应该是这样的
create table order_nature (
nature_id int primary key,
description text
);
insert into order_nature (nature_id, description)
values (1, 'sale'), (2, 'buy')
;
create table order_type (
type_id int primary key,
description text
);
insert into order_type (type_id, description)
values (1, 'type 1'), (2, 'type 2')
;
create table order_nature_type (
nature_id int references order_nature (nature_id),
type_id int references order_type (type_id),
primary key (nature_id, type_id)
);
insert into order_nature_type (nature_id, type_id)
values (1, 1), (1, 2), (2, 1), (2, 2)
;
create table sale_information (
nature_id int default 1 check (nature_id = 1),
type_id int,
foreign key (nature_id, type_id) references order_nature_type (nature_id, type_id)
);
If the foreign key
clause would also accept an expression the sale information could omit the nature_id column 如果
foreign key
子句也接受表达式,则销售信息可以省略nature_id列
create table sale_information (
type_id int,
foreign key (1, type_id) references order_nature_type (nature_id, type_id)
);
Notice the 1
in the foreign key
注意
foreign key
的1
You could use an FK to OrderType
to ensure referential integrity and a separate CHECK constraint to limit the order types. 您可以使用FK to
OrderType
来确保参照完整性,并使用单独的CHECK约束来限制订单类型。
If your OrderType
values really are that structured then a simple CHECK like this would suffice: 如果您的
OrderType
值确实是那种结构,那么像这样的简单CHECK就足够了:
check (c ~ '^sale-order-type-')
where c
is order type column in SaleInformation
其中
c
是SaleInformation
订单类型列
If the types aren't structured that way in reality, then you could add some sort of type flag to OrderType
(say a boolean is_sales
column), write a function which uses that flag to determine if an order type is a sales order: 如果类型实际上没有这样构造,那么你可以为
OrderType
添加某种类型的标志(比如一个布尔的is_sales
列),写一个使用该标志的函数来确定订单类型是否是销售订单:
create or replace function is_sales_order_type(text ot) returns boolean as $$
select exists (select 1 from OrderType where name = ot and is_sales);
$$ language sql
and then use that in your CHECK: 然后在你的CHECK中使用它:
check(is_sales_order_type(c))
You don't of course have to use a boolean is_sales
flag, you could have more structure than that, is_sales
is just for illustrative purposes. 你当然不必使用boolean
is_sales
标志,你可以有更多的结构, is_sales
只是为了说明的目的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.