我有三个名为products,customers和reserve_products的表。触发器位于保留产品表中,只有在找到客户ID和产品ID以及产品数量时才允许您插入表中。我遇到sql问题并检查行是否存在。
我的表格如下:
的产品
CREATE TABLE "SNAGEL"."PRODUCTS"
( "PID" NUMBER(6,0),
"PRODUCT_NAME" VARCHAR2(255 BYTE),
"QUANTITY" NUMBER,
"PRICE" NUMBER,
"PRODUCT_SIZE" VARCHAR2(255 BYTE),
"PRODUCT_VALUE" NUMBER,
PRIMARY KEY ("PID")
客户
CREATE TABLE "SNAGEL"."CUSTOMERS"
( "CID" NUMBER(6,0),
"FIRST_NAME" VARCHAR2(30 BYTE),
"LAST_NAME" VARCHAR2(30 BYTE),
"PHONE_NUMBER" NUMBER,
PRIMARY KEY ("CID")
储备产品
我的触发器
CREATE OR REPLACE TRIGGER reserveProductTrigger
before insert on RESERVE_PRODUCT FOR EACH ROW
DECLARE
pid products.pid%rowtype;
pidError exception;
cid customers.cid%rowtype;
cidError exception;
pidSoldout exception;
productQuantity number;
BEGIN
select cid from CUSTOMERS
where cid = :new.CID;
select COUNT(pid from products
where pid = :new.PID;
select quantity into productQuantity
from products
where pid= :new.pid;
if cid = null then
raise cidError;
elsif pid = null then
raise pidError;
elsif productQuantity = 0 then
raise pidSoldout;
else
update products
set quantity = productQuantity -1
where pid = pid;
END IF;
EXCEPTION
When cidError then
DBMS_OUTPUT.PUT_LINE('CUSTOMER not found error!');
RAISE;
When PidError then
DBMS_OUTPUT.PUT_LINE('PRODUCT not found error!');
RAISE;
When pidSoldout then
DBMS_OUTPUT.PUT_LINE('product sold out error!');
RAISE;
END;
/
答案 0 :(得分:0)
您忘记将select语句中的详细信息存储到为其创建的变量yoiu中。所以试试这个:
CREATE OR REPLACE TRIGGER reserveProductTrigger
before insert on RESERVE_PRODUCT FOR EACH ROW
DECLARE
pid products.pid%type;
pidError exception;
cid customers.cid%type;
cidError exception;
pidSoldout exception;
productQuantity number;
BEGIN
BEGIN
select cid into CID
from CUSTOMERS
where cid = :new.CID;
EXCEPTION WHEN NO_DATA_FOUND THEN
raise cidError;
END;
BEGIN
select pid
, quantity
INTO PID
, productQuantity
from products
where pid = :new.PID;
EXCEPTION WHEN NO_DATA_FOUND THEN
raise pidError;
END;
if productQuantity <= 0 then -- If it goes negative you've over
raise pidSoldout; -- committed and shouldn't accept either.
else
update products
set quantity = productQuantity -1
where pid = pid;
END IF;
EXCEPTION
When cidError then
DBMS_OUTPUT.PUT_LINE('CUSTOMER not found error!');
RAISE;
When PidError then
DBMS_OUTPUT.PUT_LINE('PRODUCT not found error!');
RAISE;
When pidSoldout then
DBMS_OUTPUT.PUT_LINE('product sold out error!');
RAISE;
END;
/
但是,您应该使用参照完整性约束,而不是依靠触发器来检查PID和CID的存在。此外,您可以在产品中的数量列上设置检查约束,要求它为&gt; = 0。
然后你在触发器中唯一需要做的就是减少数量:
CREATE TABLE "PRODUCTS"
( "PID" NUMBER(6,0),
"PRODUCT_NAME" VARCHAR2(255 BYTE),
"QUANTITY" NUMBER CONSTRAINT PRODUCT_MIN_QUANTITY CHECK (QUANTITY >= 0), -- Add Check constraint here
"PRICE" NUMBER,
"PRODUCT_SIZE" VARCHAR2(255 BYTE),
"PRODUCT_VALUE" NUMBER,
CONSTRAINT PRODUCTS_PK PRIMARY KEY ("PID") -- Name the PK Constraint
);
CREATE TABLE "CUSTOMERS"
( "CID" NUMBER(6,0),
"FIRST_NAME" VARCHAR2(30 BYTE),
"LAST_NAME" VARCHAR2(30 BYTE),
"PHONE_NUMBER" NUMBER,
CONSTRAINT CUSTOMERS_PK PRIMARY KEY ("CID") -- Name the PK Constraint
);
create table reserve_product (
PID NOT NULL CONSTRAINT reserve_product_fk REFERENCES products(PID) -- Use referential integrity here
, CID NOT NULL CONSTRAINT reserve_product_fk REFERENCES customers(CID) -- and here
)
CREATE OR REPLACE TRIGGER reserveProductTrigger
before insert on RESERVE_PRODUCT FOR EACH ROW
BEGIN
update products
set quantity = quantity -1
where pid = :new.pid;
END;
/
现在,如果产品或客户分别缺少PID或CID,或者产品记录的数量为0,则会引发相应的异常。
答案 1 :(得分:0)
CREATE OR REPLACE TRIGGER trg_reserve_products
BEFORE INSERT ON reserve_products
FOR EACH ROW
DECLARE
v_count NUMBER;
v_p_id NUMBER(6);
v_c_id NUMBER(6);
v_p_quantity products.p_quantity%TYPE;
v_p_name products.p_name%TYPE;
BEGIN
SELECT COUNT(*)
INTO v_count
FROM products
WHERE p_id = :NEW.p_id;
IF v_count = 0 THEN
raise_application_error(-20000 , 'Invalid Product ID.');
END IF;
SELECT COUNT(*)
INTO v_count
FROM customers
WHERE c_id = :NEW.c_id;
IF v_count IS NULL THEN
raise_application_error(-20000 , 'Invalid Customer ID.');
END IF;
SELECT p_quantity, p_name
INTO v_p_quantity, v_p_name
FROM products
WHERE p_id = :NEW.p_id;
IF v_p_quantity < 1 THEN
raise_application_error(-20000 , v_p_name || ' 4 is currently out of stock.');
END IF;
UPDATE products
SET p_quantity = p_quantity - 1
WHERE p_id = :NEW.p_id;
END trg_reserve_products;
SELECT * FROM products;
INSERT INTO reserve_products VALUES(1, 101, 1);
INSERT INTO reserve_products VALUES(2, 46, 1);
INSERT INTO reserve_products VALUES(3, 46, 2);
INSERT INTO reserve_products VALUES(4, 46, 3);
SELECT * FROM products;
SELECT * FROM reserve_products;