2014-02-08 46 views
6

我有一個參照表,說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'); 

我希望建立從另一個表FK約束,說SaleInformation,指向該表(OrderType)。但是,我想表達的是,並非所有行OrderType都符合該FK的目的(它只應該是與銷售相關的訂單類型)。

我想到只用正確的行(圖SaleOrderType)的創建表OrderType的景色,加上FK約束這一觀點,但PostgreSQL的不太願意與:

ERROR: referenced relation "SaleOrderType" is not a table 

如此看來我無法爲視圖創建FK約束(爲什麼?)。我只剩下創建冗餘表來保存與銷售相關的訂單類型的選項嗎?另一種方法是簡單地讓FK指向原始表格,但是我並沒有嚴格按照我的意願表達約束條件。

+0

如何讓OrderType結構如下:id_order_type爲serial(pk),order_type爲字符變化,type_不同的order_type字符:從SaleInformation引用id_order_type? – Houari

+1

編輯您的問題,並將CREATE TABLE語句粘貼到OrderType中。 –

回答

6

我覺得你的方案應該是這樣的

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) 
); 

如果foreign key條款也將接受一個表達式的銷售信息可以省略nature_id列

create table sale_information (
    type_id int, 
    foreign key (1, type_id) references order_nature_type (nature_id, type_id) 
); 

注意的1foreign key

+0

如果省略'sale_information'表中的'nature_id'列,如何可以製作兩列的FK?像這樣的東西似乎更加正確:'外鍵(type_id)引用order_nature_type(1,type_id)'或'外鍵(type_id)引用order_nature_type(type_id)where [order_nature_type] .nature_id = 1'只有我不確定如果他們工作。怎麼能做到這樣的事情? – orad

+0

FK +檢查約束思想的變體:如果'order_nature'和'order_type'不是很大的表,'order_nature_type'可以有一個ID列,其值爲'nature_id *'_some_ _constant_'+ type_id'。檢查約束可以進行除法或按位AND'來從合併的ID檢索'nature_id'。 是的,它有點兒家常。但我面臨着類似的事情,這是迄今爲止我所提出的最不溫順的事情。而另一種選擇(數十個小桌子不斷增長)是一個煩惱,逐漸變成一場噩夢。 – unbob

1

您可以使用FK OrderType以確保參照完整性和單獨的CHECK約束來限制訂單類型。

如果您OrderType值真的是結構性那麼像這樣一個簡單的檢查就足夠了:

check (c ~ '^sale-order-type-') 

其中cSaleInformation

訂單類型列。如果類型不規整以這種方式現實,那麼你可以添加某種類型的標誌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 

,然後用它在你的檢查:

check(is_sales_order_type(c)) 

你當然不是必須使用一個布爾is_sales標誌,你可以有比這更結構,is_sales僅僅是用於說明目的。