2016-06-07 171 views
0

需要你的幫助檢查約束

我有一個表在這類的Oracle SQL Developer:

 
Issue 
ID|Subscriber_ID|Book_ID| Taken |Returned 
--+-------------+-------+--------+-------- 
1 | 1   | 2 |01-06-16|05-06-16 
2 | 3   | 5 |07-05-16| (null) 
3 | 2   | 2 |06-06-16| (null) 
4 | 1   | 3 |17-05-16|26-05-16 

這是某種在返回的列來圖書館的圖書發行,其中(空)的這本書還沒有歸還。我需要創建驗證規則,以避免發佈未返回的書(例如,我目前無法拿到第5本書)。我怎樣才能實現它?

+0

你不能。不是一個約束。你可以創建一個函數/過程來做到這一點。無法創建約束來檢查以前的行。一個函數會爲你服務嗎? –

回答

1

嗯。你不能用check約束來做到這一點,因爲它們只適用於一行中的值。

你想確保的是你沒有兩本書的返回值。有些數據庫支持過濾的唯一索引:

create unique index on unq_issue_bookid on issue(book_id) where returned is null; 

但不是Oracle。你可以做一個基於函數的索引非常相似的東西:

create unique index on unq_issue_bookid_returned 
    on issue(book_id, 
      (case when returned is not null then id else -1 end) 
      ); 

這將有利於讓每本書只有一個NULL值相同的效果。

0

你可以做到這一點:

CREATE TABLE table_name (ID, Subscriber_ID, Book_ID, Taken, Returned) AS 
SELECT 1, 1, 2, DATE '2016-06-01', DATE '2016-06-05' FROM DUAL UNION ALL 
SELECT 2, 3, 5, DATE '2016-05-07', NULL FROM DUAL UNION ALL 
SELECT 3, 2, 2, DATE '2016-06-06', NULL FROM DUAL UNION ALL 
SELECT 4, 1, 3, DATE '2016-05-17', DATE '2016-05-26' FROM DUAL; 

ALTER TABLE table_name ADD is_borrowed 
    GENERATED ALWAYS AS (CASE WHEN returned IS NULL THEN 1 END) VIRTUAL; 

ALTER TABLE TABLE_NAME ADD CONSTRAINT is_borrowed__u 
    UNIQUE(book_id, is_borrowed); 

然後:

INSERT INTO table_name (ID, Subscriber_ID, Book_ID, Taken) 
VALUES (5, 2, 5, DATE '2016-06-06'); 

將失敗:

SQL Error: ORA-00001: unique constraint (TEST.IS_BORROWED__U) violated 
+0

謝謝,但是這個解決方案不起作用,因爲當書一旦你不能再返回時它就返回了(對(book_id,null)也必須是唯一的) – JGDger