2016-06-07 178 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