0

need your help

I have a table in Oracle SQL Developer of this kind:

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

It's some sort of library book issuing where (null) in Returned column means that this book wasn't returned yet. I need to create validation rule to avoid issuing book that wasn't returned (e.g. I can't take the book #5 at the moment). How can I implement it?

JGDger
  • 105
  • 1
  • 5
  • You can't. Not as a constraint. You can create a function/procedure to do so. A constraint can't be created to check previous rows. Would a function serves you? – Jorge Campos Jun 07 '16 at 19:56

2 Answers2

1

Hmmm. You can't do this with a check constraint, because those only apply to values in one row.

What you want to ensure is that you do not have two returned values for a book. Some databases support filtered unique indexes:

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

But not Oracle. You can do something very similar with a function-based index:

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

This will have the same effect of allowing only one NULL value per book.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
0

You can do it with :

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

Then:

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

Will fail with:

SQL Error: ORA-00001: unique constraint (TEST.IS_BORROWED__U) violated
MT0
  • 143,790
  • 11
  • 59
  • 117
  • Thank you, but this solution doesn't work because when the book was returned once you cannot return it again (pair (book_id, null) must be unique too) – JGDger Jun 09 '16 at 14:16