This is kinda long, but actually quite straightforward.
Tested on a Oracle 10gR2 setup.
Table:
CREATE TABLE books
(
book_id INTEGER NOT NULL,
no_of_copies INTEGER NOT NULL,
CONSTRAINT pk_book_id PRIMARY KEY (book_id)
);
CREATE TABLE copies
(
book_id INTEGER NOT NULL,
copy_no INTEGER NOT NULL,
CONSTRAINT fk_book_id FOREIGN KEY (book_id) REFERENCES books (book_id) ON DELETE CASCADE
);
Then trigger:
CREATE TRIGGER tri_books_add
AFTER INSERT ON books
FOR EACH ROW
DECLARE
num INTEGER:=1;
BEGIN
IF :new.no_of_copies>0 THEN
WHILE num<=:new.no_of_copies LOOP
INSERT INTO copies (book_id,copy_no) VALUES (:new.book_id,num);
num:=num+1;
END LOOP;
END IF;
END;
/
CREATE TRIGGER tri_books_edit
BEFORE UPDATE ON books
FOR EACH ROW
DECLARE
num INTEGER:=1;
BEGIN
IF :new.no_of_copies<:old.no_of_copies THEN
RAISE_APPLICATION_ERROR(-20001,'Decrease of copy number prohibited.');
ELSIF :new.no_of_copies>:old.no_of_copies THEN
SELECT max(copy_no)+1 INTO num FROM copies WHERE book_id=:old.book_id;
WHILE num<=:new.no_of_copies LOOP
INSERT INTO copies (book_id,copy_no) VALUES (:old.book_id,num);
num:=num+1;
END LOOP;
END IF;
END;
/
What the trigger do:
- For the
tri_books_add
- use a
num
to "remember" copy_no
;
- use a
WHILE-LOOP
statement to add copies.
- For the
tri_books_edit
- use a
num
to "remember" copy_no
;
- check if new
no_of_copies
is illegally decreased; if so, raise a custom error;
- append copies.
The reason I separate books inserting and editing into two triggers, is because I employed a foreign key
constraint, so after insert
would be needed for inserting (correct me if I'm wrong on this, though).
I then run some test:
INSERT INTO books (book_id,no_of_copies) VALUES (1,3);
INSERT INTO books (book_id,no_of_copies) VALUES (2,5);
SQL> select * from copies;
BOOK_ID COPY_NO
---------- ----------
1 1
1 2
1 3
2 1
2 2
2 3
2 4
2 5
8 rows selected.
SQL> update books set no_of_copies=5 where book_id=1;
1 row updated.
SQL> select * from copies;
BOOK_ID COPY_NO
---------- ----------
1 1
1 2
1 3
2 1
2 2
2 3
2 4
2 5
1 4
1 5
10 rows selected.
SQL> update books set no_of_copies=3 where book_id=1;
update books set no_of_copies=3 where book_id=1
*
ERROR at line 1:
ORA-20001: Decrease of copy number prohibited.
ORA-06512: at "LINEQZ.TRI_BOOKS_EDIT", line 5
ORA-04088: error during execution of trigger 'LINEQZ.TRI_BOOKS_EDIT'
(I don't seem to be able to make sqlfiddle to work on triggers so no online demos, sorry.)