2015-09-22 11 views
1

例子:
我:定義外鍵到目標表的子集

Table A: 
int id 
int table_b_id 

Table B: 
int id 
text type 

我想加上列table_b_id約束檢查將驗證它僅指向表中的行B它們的類型值是'X'。
我無法更改表格結構。
我明白它可以通過'CHECK'和一個postgres函數來完成,它會執行特定的查詢,但我看到有人建議避免它。
關於什麼是實施它的最佳方法的任何輸入將會有所幫助。

回答

0

你所指的不是FOREIGN KEY,在PostgreSQL中,它指的是在其他表中有一列(多個),其中有一個唯一的索引在那個/那些列上,當這些/那些列的值發生變化時(可能有相關的自動操作)(ON UPDATE,ON 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'; 
+0

我可以定義一個子表繼承只包括原始錶行的一部分嗎? –

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

ERROR: insert or update on table "a" violates foreign key constraint "a_b_id_fkey" Detail: Key (b_id)=(2) is not present in table "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 | 
+0

感謝您的教育解決方案,但由於我無法更改數據庫模式,它不會解決我目前的問題。這在未來的場景中肯定會很有用。 –