如上述標題所述。 假設我有3張桌子。DB2 SQL多級觸發器級聯
--table A, B, C
和兩個觸發器,旨在級聯:
--trigger X, Y
create trigger X
after insert on A
...(some codes)
update B set ...(some codes);
--and
create trigger Y
after update on B
...(some codes)
insert into C values (...(some codes));
其中:
--insert on A fire X to update B, then again fire Y to insert on C.
但問題是第一個觸發X而沒有問題,但第二個觸發Y被不被解僱第一次發射後。
上述代碼可能存在什麼問題?
對於我的項目,我創建了一個微型倉庫數據庫來測試所有實體。以下是我迄今爲止所做的代碼。
--create tables, no error over here i assumed
CREATE TABLE VENUE(
VENUE_ID DECIMAL(3,0) NOT NULL CHECK (VENUE_ID BETWEEN 111 AND 333),
VENUE_FLOOR INT NOT NULL CHECK (VENUE_FLOOR IN (1,2,3)),
VENUE_SECTION INT NOT NULL CHECK (VENUE_SECTION IN (1,2,3)),
PRIMARY KEY (VENUE_ID)
)@
CREATE TABLE CLIENT(
CLIENT_ID DECIMAL(5,0) NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 10000 INCREMENT BY 1) CHECK (CLIENT_ID BETWEEN 10000 AND 99999),
CLIENT_FNAME VARCHAR(30) NOT NULL,
CLIENT_LNAME VARCHAR(30) NOT NULL,
CLIENT_PHONE VARCHAR(12) NOT NULL,
CLIENT_ADDRS VARCHAR(300) NOT NULL,
PRIMARY KEY (CLIENT_ID),
CONSTRAINT CLIENT_PHONE_UNQ UNIQUE (CLIENT_PHONE)
)@
CREATE TABLE COURIER(
COURIER_ID DECIMAL(3,0) NOT NULL CHECK (COURIER_ID BETWEEN 100 AND 999),
COURIER_FNAME VARCHAR(30) NOT NULL,
COURIER_LNAME VARCHAR(30) NOT NULL,
COURIER_PHONE VARCHAR(12) NOT NULL,
PRIMARY KEY (COURIER_ID),
CONSTRAINT COURIER_PHONE_UNQ UNIQUE (COURIER_PHONE)
)@
CREATE TABLE STOCK(
STOCK_ID DECIMAL(8,0) NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 10000000 INCREMENT BY 1) CHECK (STOCK_ID BETWEEN 10000000 AND 19999999),
STOCK_NAME VARCHAR(20) NOT NULL,
SUPPLIER_NAME VARCHAR(50) NOT NULL,
STOCK_QTY INT NOT NULL DEFAULT 0,
VENUE_ID DECIMAL(3,0) NOT NULL,
PRIMARY KEY (STOCK_ID),
FOREIGN KEY (VENUE_ID) REFERENCES VENUE ON DELETE no action,
CONSTRAINT STOCK_NAME_UNQ UNIQUE (STOCK_NAME),
CONSTRAINT SUPPLIER_NAME_UNQ UNIQUE (SUPPLIER_NAME)
)@
--CREATE TRIGGER/PROCEDURE CHECK STOCK_QTY - ORDER_QUANTITY >= 100--
CREATE TABLE ORDER(
ORDER_ID DECIMAL(11,0) NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 10000000000 INCREMENT BY 1) CHECK (ORDER_ID BETWEEN 10000000000 AND 99999999999),
ORDER_QTY INT NOT NULL CHECK (ORDER_QTY BETWEEN 10 AND 999),
CLIENT_ID DECIMAL(5,0) NOT NULL,
STOCK_ID DECIMAL(8,0) NOT NULL,
PRIMARY KEY (ORDER_ID),
FOREIGN KEY (CLIENT_ID) REFERENCES CLIENT(CLIENT_ID) ON DELETE no action,
FOREIGN KEY (STOCK_ID) REFERENCES STOCK(STOCK_ID) ON DELETE no action
)@
CREATE TABLE DELIVERY(
DELIVERY_ID DECIMAL(11,0) NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 16900000000 INCREMENT BY 1) CHECK (DELIVERY_ID BETWEEN 16900000000 AND 16999999999),
ORDER_ID DECIMAL(11,0) NOT NULL,
COURIER_ID DECIMAL(3,0),
PRIMARY KEY(DELIVERY_ID),
FOREIGN KEY(ORDER_ID)REFERENCES ORDER(ORDER_ID) ON DELETE no action,
FOREIGN KEY(COURIER_ID)REFERENCES COURIER(COURIER_ID) ON DELETE no action,
CONSTRAINT ORDER_ID_DELI_UNQ UNIQUE (ORDER_ID)
)@
--TO SELECT FOR LOG- USE SELECT TIMESTAMP(LOG_ID), ... FROM [email protected]
CREATE TABLE LOG(
LOG_ID CHAR(13) NOT NULL FOR BIT DATA,
LOG_PROCESS VARCHAR(9) NOT NULL CHECK (LOG_PROCESS IN ('Stock-in','Stock-out')),
LOG_QTY INT NOT NULL CHECK(LOG_QTY BETWEEN 10 AND 999),
LOG_DATE DATE NOT NULL,
DELIVERY_ID DECIMAL(11,0),
STOCK_ID DECIMAL(8,0) NOT NULL,
PRIMARY KEY(LOG_ID),
FOREIGN KEY(DELIVERY_ID)REFERENCES DELIVERY(DELIVERY_ID),
FOREIGN KEY(STOCK_ID)REFERENCES STOCK(STOCK_ID)
--CONSTRAINT DELIVERY_ID_LOG_UNQ UNIQUE (DELIVERY_ID)
)@
插入一些值測試:
--INSERT INTO TABLE--
INSERT INTO VENUE VALUES (111,1,1)@
INSERT INTO VENUE VALUES (112,2,2)@
INSERT INTO VENUE VALUES (113,3,3)@
INSERT INTO CLIENT VALUES (DEFAULT,'ROAN','CHENG','60189774541','28 JLN APA')@
INSERT INTO CLIENT VALUES (DEFAULT,'AAA','ABC','601','29 JLJ AAA')@
INSERT INTO CLIENT VALUES (DEFAULT,'BBB','BBC','60111234567','30 JLN BBB')@
INSERT INTO COURIER VALUES (100,'DHL','EXP','60355006666')@
INSERT INTO COURIER VALUES (200,'ABX','EXP','60344007777')@
INSERT INTO COURIER VALUES (300,'POS','LAJU','61300882525')@
INSERT INTO STOCK VALUES (DEFAULT,'IPHONE 7','APPLE',100,111)@
INSERT INTO STOCK (STOCK_ID,STOCK_NAME,SUPPLIER_NAME,VENUE_ID) VALUES (10000001,'SAMSUNG S7','SAMSUNG',112)@
INSERT INTO STOCK VALUES (DEFAULT,'MMU','TM',300,113)@
INSERT INTO STOCK VALUES (DEFAULT,'CINEMA','TGV',200,111)@
INSERT INTO STOCK VALUES (DEFAULT,'FOO','FOOCORP',1000,113)@
INSERT INTO ORDER VALUES (DEFAULT,10,10000,10000003)@
INSERT INTO ORDER VALUES (DEFAULT,20,10000,10000002)@
INSERT INTO ORDER VALUES (DEFAULT,30,10002,10000002)@
和觸發部,以正確的順序級聯層
--TRIGGER--
-------------------------------------------------------------------------------------------------------
--1)AUTO CREATE DELIVERY AFTER PLACING ORDER (no error)
CREATE TRIGGER REQUEST_DELIVERY
AFTER INSERT ON ORDER
REFERENCING NEW AS N
for each row mode db2sql
INSERT INTO DELIVERY VALUES (
DEFAULT,
N.ORDER_ID,
NULL
)@
--2)UPDATE STOCK QTY AFTER ISSUED A SUCCESSFUL DELIVERY (UPDATE DELIVERY WITH COURIER_ID MEANS PARCEL HAS
-- BEEN MAILED OUT)
--(error here, sqlstate="21000" & "09000",for trigger "...UPDATELOG)
drop trigger [email protected]
CREATE TRIGGER UPDATESTOCK_STOCKOUT
AFTER UPDATE OF COURIER_ID ON DELIVERY
REFERENCING OLD AS O
FOR EACH ROW MODE DB2SQL
BEGIN
UPDATE STOCK
SET STOCK_QTY = STOCK_QTY - (SELECT ORDER_QTY FROM ORDER WHERE ORDER.ORDER_ID = O.ORDER_ID)
WHERE STOCK_ID IN (SELECT STOCK_ID FROM ORDER WHERE ORDER.ORDER_ID = O.ORDER_ID);
[email protected]
--NOT WORKING EITHER FOR BELOW ALTERNATIVES--
----------------------------------------------------------------------------------------------
CREATE PROCEDURE UPDATEDELIVERY(IN ORD_ID DECIMAL(11,0), COU_ID DECIMAL(3,0))
BEGIN
UPDATE DELIVERY SET COURIER_ID = COU_ID WHERE ORDER_ID = ORD_ID;
--UPDATE STOCK SET STOCK_QTY = STOCK_QTY - (SELECT ORDER_QTY FROM ORDER WHERE ORDER.ORDER_ID = ORD_ID);
[email protected]
DROP PROCEDURE [email protected]
CREATE PROCEDURE UPDATEDELIVERY2(IN DLV_ID DECIMAL(11,0), COU_ID DECIMAL(3,0))
BEGIN
UPDATE DELIVERY SET COURIER_ID = COU_ID WHERE DELIVERY_ID = DLV_ID;
--UPDATE STOCK SET STOCK_QTY = STOCK_QTY - (SELECT ORDER_QTY FROM ORDER WHERE ORDER.ORDER_ID = (SELECT ORDER_ID FROM DELIVERY D WHERE D.DELIVERY_ID = DLV_ID))
--WHERE STOCK_ID = (SELECT STOCK_ID FROM ORDER O, DELIVERY D WHERE D.DELIVERY_ID = DLV_ID AND D.ORDER_ID = O.ORDER_ID);
[email protected]
---------------------------------------------------------------------------------------------
--3)auto update delivery.COURIER_ID once stock out in log
--(error here, sqlstate="21000" & "09000",for trigger "...UPDATELOG)
drop trigger [email protected]
CREATE TRIGGER UPDATELOG
AFTER UPDATE OF STOCK_QTY ON STOCK
REFERENCING OLD AS O
FOR EACH ROW MODE DB2SQL
BEGIN
IF O.STOCK_QTY < (SELECT STOCK_QTY FROM STOCK WHERE STOCK_ID = O.STOCK_ID) THEN
--STOCKIN
INSERT INTO LOG VALUES (
GENERATE_UNIQUE(),
'Stock-in',
((SELECT STOCK_QTY FROM STOCK WHERE STOCK_ID = O.STOCK_ID) - O.STOCK_QTY),
CURRENT DATE,
NULL,
O.STOCK_ID
);
--UPDATE STOCK
--SET STOCK_QTY = STOCK_QTY - (SELECT ORDER_QTY FROM ORDER WHERE ORDER.ORDER_ID = O.ORDER_ID AND ORDER.STOCK_ID = STOCK.STOCK_ID);
ELSEIF O.STOCK_QTY > (SELECT STOCK_QTY FROM STOCK WHERE STOCK_ID = O.STOCK_ID) THEN
--STOCKOUT
INSERT INTO LOG VALUES (
GENERATE_UNIQUE(),
'Stock-out',
(O.STOCK_QTY - (SELECT STOCK_QTY FROM STOCK WHERE STOCK_ID = O.STOCK_ID)),
CURRENT DATE,
(SELECT DELIVERY_ID FROM DELIVERY D, ORDER WHERE D.ORDER_ID = ORDER.ORDER_ID AND ORDER.STOCK_ID = O.STOCK_ID),
O.STOCK_ID
);
END IF;
[email protected]
我讀SQLCODE和SQLSTATE的文檔錯誤,並且它說錯誤與觸發器和一些返回多個值的select語句有關。
但是,當測試觸發器中的所有select語句(子查詢和查詢)時,它全部只返回1個值,該值無誤地工作。 PS:請幫助我指導我做解釋正確的事情,而不是給我直接的答案,我的大腦陷入了這種SQL流量。如果我無法從這節課中學到任何東西,那麼我就正式註定了。
這可能是代碼真正的問題,我必須先嚐試一下,謝謝。順便說一下,我試着創建3個虛擬表(每個表中有兩列的A,B,C)和2個旨在級聯的觸發器(X,Y和X fire Y)。但它並不按我期望的方式工作。 –
再次感謝你,因爲那正是我的代碼中的錯誤,現在我創建了一個臨時表temp,在此臨時存儲DELIVERY表中的唯一ORDER_ID以用於UPDATELOG觸發器。 –