[英]Oracle SQL Trigger insert new records based on a insert column value
我正在嘗試為Oracle表創建觸發器。 這是我有兩個表的要求書籍,副本(書籍和副本之間存在1到n的關系。每本書可以具有0到n個副本)
圖書表:
CREATE TABLE Book
(
book_id INTEGER NOT NULL ,
isbn VARCHAR2 (20) NOT NULL,
publisher_id INTEGER NOT NULL ,
tittle VARCHAR2 (100) NOT NULL ,
cat_id INTEGER NOT NULL ,
no_of_copies INTEGER NOT NULL ,
....
CONSTRAINT isbn_unique UNIQUE (isbn),
CONSTRAINT shelf_letter_unique UNIQUE (shelf_letter, call_number)
) ;
份數表
CREATE TABLE Copies
(
copy_id INTEGER NOT NULL ,
book_id INTEGER NOT NULL ,
copy_number INTEGER NOT NULL,
constraint copy_number_unique unique(book_id,copy_number)
) ;
觸發器(在更新,編輯Book表時)應將其相應的副本記錄添加到Copies表中。 因此,如果插入到Books表中的Book.no_of_copies為5,則應在Copies表中插入五個新記錄。
下面的代碼適用於表BOOK中的INSERT和UPDATE。 僅當在表BOOK中插入新行或用大於當前值的no_of_copies更新表BOOK中的現有行時,才在COPIES表中插入行。
表創建:
CREATE TABLE Book
(
book_id INTEGER NOT NULL ,
isbn VARCHAR2 (20) NOT NULL,
publisher_id INTEGER NOT NULL ,
tittle VARCHAR2 (100) NOT NULL ,
cat_id INTEGER NOT NULL ,
no_of_copies INTEGER NOT NULL ,
CONSTRAINT isbn_unique UNIQUE (isbn)
) ;
CREATE TABLE Copies
(
copy_id INTEGER NOT NULL ,
book_id INTEGER NOT NULL ,
copy_number INTEGER NOT NULL,
constraint copy_number_unique unique(book_id,copy_number)
);
CREATE SEQUENCE COPY_SEQ
MINVALUE 1
MAXVALUE 999999
START WITH 1
INCREMENT BY 1
NOCACHE;
觸發:
CREATE OR REPLACE TRIGGER TR_TEST
BEFORE INSERT OR UPDATE ON BOOK
FOR EACH ROW
DECLARE
V_CURR_COPIES NUMBER;
V_COUNT NUMBER := 0;
BEGIN
IF :NEW.NO_OF_COPIES > NVL(:OLD.NO_OF_COPIES, 0) THEN
SELECT COUNT(1)
INTO V_CURR_COPIES --# of rows in COPIES table for a particular book.
FROM COPIES C
WHERE C.BOOK_ID = :NEW.BOOK_ID;
WHILE V_COUNT < :NEW.NO_OF_COPIES - V_CURR_COPIES
LOOP
INSERT INTO COPIES
(
COPY_ID,
BOOK_ID,
COPY_NUMBER
)
SELECT COPY_SEQ.NEXTVAL,
:NEW.BOOK_ID,
V_COUNT + V_CURR_COPIES + 1
FROM DUAL;
V_COUNT := V_COUNT + 1;
END LOOP;
END IF;
END;
測試:
INSERT INTO BOOK
VALUES (1, 'ABCDEF', 2, 'TEST BOOK', 1, 3);
UPDATE BOOK B
SET B.NO_OF_COPIES = 4
WHERE B.BOOK_ID = 1;
這有點長,但實際上非常簡單。
在Oracle 10gR2設置上進行了測試。
表:
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
);
然后觸發:
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;
/
觸發器的作用是:
tri_books_add
num
“記住” copy_no
; WHILE-LOOP
語句添加副本。 tri_books_edit
之所以將書籍的插入和編輯分為兩個觸發器,是因為我采用了foreign key
約束 ,因此after insert
需要插入(但是如果我錯了,請更正我)。
然后,我運行一些測試:
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'
(我似乎無法使sqlfiddle在觸發器上工作,所以抱歉,沒有在線演示。)
create or replace
trigger BOOK_TRIGGER
AFTER INSERT ON BOOK
FOR EACH ROW
DECLARE L_COPIES NUMBER:= :NEW.NO_OF_COPIES;
BEGIN
FOR I IN 1..5
LOOP
INSERT
INTO COPIES
(
COPY_ID,
BOOK_ID,
COPY_NUMBER
)
VALUES
(
1, -- your copy sequence
:new.book_id,
i
);
END LOOP;
END;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.