未引发触发 if-else 语句错误
Trigger if-else statement error not being raised
我已经创建了一个程序和一个触发器,我打算支付票价,输入的票价金额必须大于或等于付款中的确切金额 Table
从table开始,我的意思是,用户需要输入足够的金额才能继续存储过程,如果输入的金额低于该金额,则会引发触发器错误!
程序
CREATE OR REPLACE PROCEDURE PRC_PAY_TRIP
(CUST_ID IN NUMBER,PAYMENT_ID IN NUMBER,PAYMENT_TYPE IN VARCHAR2,AMT_PAY IN NUMBER)
AS
v_paymentstatus VARCHAR2(15) := 'Paid';
v_temppaymentid NUMBER(4) := PAYMENT_ID;
v_truenumber NUMBER(10);
no_null_on_custID EXCEPTION;
no_null_on_payID EXCEPTION;
invalid_paymentid EXCEPTION;
invalid_paymenttype EXCEPTION;
invalid_paymentamt EXCEPTION;
BEGIN
v_truenumber := v_temppaymentid-1000;
IF CUST_ID < 0
THEN
RAISE no_null_on_custID;
END IF;
IF PAYMENT_ID < 0
THEN
RAISE no_null_on_payID;
END IF;
IF CUST_ID ^= v_truenumber THEN
RAISE invalid_paymentid;
END IF;
IF PAYMENT_TYPE ^= 'Cash' AND PAYMENT_TYPE ^= 'E-Wallet' THEN
RAISE invalid_paymenttype;
END IF;
IF AMT_PAY < 0 THEN
RAISE invalid_paymentamt;
END IF;
UPDATE Payment
SET paymenttype = PAYMENT_TYPE,paymentdate = TO_CHAR(sysdate,'DD/MON/YYYY'), paymentstatus = v_paymentstatus
where paymentid = PAYMENT_ID;
EXCEPTION
WHEN no_null_on_custID then
DBMS_OUTPUT.PUT_LINE('Invalid Customer ID');
WHEN no_null_on_payID then
DBMS_OUTPUT.PUT_LINE('Invalid Payment ID');
WHEN invalid_paymenttype then
DBMS_OUTPUT.PUT_LINE('You can either choose Cash or E-Wallet only!');
WHEN invalid_paymentid then
DBMS_OUTPUT.PUT_LINE('Payment id is not yours, just add 1000 from your Customer ID and that will be your Payment ID');
WHEN invalid_paymentamt then
DBMS_OUTPUT.PUT_LINE('Amount pay cannot be negative value!');
END;
/
触发
CREATE OR REPLACE trigger trg_payment_validation
before update on payment
for each row
BEGIN
if :NEW.paymentamount < :OLD.paymentamount then >>> this error could not be raised even after
the amount entered is lower than the
actual amount
RAISE_APPLICATION_ERROR(
-20950,
'Insufficient amount entered, pls pay the exact amount'
);
elsif :OLD.paymentstatus = 'Paid' then
RAISE_APPLICATION_ERROR(
-20950,
'You cannot pay the fares as you already paid before this, have a nice day'
);
end if;
END;
/
当您手动更新 table 时,触发器会按预期工作。
当从过程中调用时,触发器不会报告无效金额,并显示已支付的全部金额,即使它不是 - 支付金额未更改,但其他列已更改。
那是因为你程序的更新语句是:
UPDATE Payment
SET paymenttype = PAYMENT_TYPE,
paymentdate = TO_CHAR(sysdate,'DD/MON/YYYY'),
paymentstatus = v_paymentstatus
where paymentid = PAYMENT_ID;
您没有告诉它更新金额,因此触发器没有修改后的 :new
值 - 新旧值相同。您需要在更新中包括该列:
UPDATE Payment
SET paymenttype = PAYMENT_TYPE,
paymentdate = TO_CHAR(sysdate,'DD/MON/YYYY'),
paymentamount = amt_pay,
paymentstatus = v_paymentstatus
where paymentid = PAYMENT_ID;
TO_CHAR(sysdate,'DD/MON/YYYY')
看起来很奇怪 - table 列应该是日期而不是字符串,因此您不应该将该值转换为字符串;如果该列是日期,那么您将依靠客户端的 NLS 设置将其转换回来。如果您想忽略当前时间,则可以改为 TRUNC(sysdate)
。
您也不应该依赖过程主体中的 dbms_output
- 您无法控制调用它的人是否启用了输出,因此他们可能永远看不到问题。当您在触发器中引发异常时,您可以在其他错误的过程中执行相同的操作。
我已经创建了一个程序和一个触发器,我打算支付票价,输入的票价金额必须大于或等于付款中的确切金额 Table
从table开始,我的意思是,用户需要输入足够的金额才能继续存储过程,如果输入的金额低于该金额,则会引发触发器错误!
程序
CREATE OR REPLACE PROCEDURE PRC_PAY_TRIP
(CUST_ID IN NUMBER,PAYMENT_ID IN NUMBER,PAYMENT_TYPE IN VARCHAR2,AMT_PAY IN NUMBER)
AS
v_paymentstatus VARCHAR2(15) := 'Paid';
v_temppaymentid NUMBER(4) := PAYMENT_ID;
v_truenumber NUMBER(10);
no_null_on_custID EXCEPTION;
no_null_on_payID EXCEPTION;
invalid_paymentid EXCEPTION;
invalid_paymenttype EXCEPTION;
invalid_paymentamt EXCEPTION;
BEGIN
v_truenumber := v_temppaymentid-1000;
IF CUST_ID < 0
THEN
RAISE no_null_on_custID;
END IF;
IF PAYMENT_ID < 0
THEN
RAISE no_null_on_payID;
END IF;
IF CUST_ID ^= v_truenumber THEN
RAISE invalid_paymentid;
END IF;
IF PAYMENT_TYPE ^= 'Cash' AND PAYMENT_TYPE ^= 'E-Wallet' THEN
RAISE invalid_paymenttype;
END IF;
IF AMT_PAY < 0 THEN
RAISE invalid_paymentamt;
END IF;
UPDATE Payment
SET paymenttype = PAYMENT_TYPE,paymentdate = TO_CHAR(sysdate,'DD/MON/YYYY'), paymentstatus = v_paymentstatus
where paymentid = PAYMENT_ID;
EXCEPTION
WHEN no_null_on_custID then
DBMS_OUTPUT.PUT_LINE('Invalid Customer ID');
WHEN no_null_on_payID then
DBMS_OUTPUT.PUT_LINE('Invalid Payment ID');
WHEN invalid_paymenttype then
DBMS_OUTPUT.PUT_LINE('You can either choose Cash or E-Wallet only!');
WHEN invalid_paymentid then
DBMS_OUTPUT.PUT_LINE('Payment id is not yours, just add 1000 from your Customer ID and that will be your Payment ID');
WHEN invalid_paymentamt then
DBMS_OUTPUT.PUT_LINE('Amount pay cannot be negative value!');
END;
/
触发
CREATE OR REPLACE trigger trg_payment_validation
before update on payment
for each row
BEGIN
if :NEW.paymentamount < :OLD.paymentamount then >>> this error could not be raised even after
the amount entered is lower than the
actual amount
RAISE_APPLICATION_ERROR(
-20950,
'Insufficient amount entered, pls pay the exact amount'
);
elsif :OLD.paymentstatus = 'Paid' then
RAISE_APPLICATION_ERROR(
-20950,
'You cannot pay the fares as you already paid before this, have a nice day'
);
end if;
END;
/
当您手动更新 table 时,触发器会按预期工作。
当从过程中调用时,触发器不会报告无效金额,并显示已支付的全部金额,即使它不是 - 支付金额未更改,但其他列已更改。
那是因为你程序的更新语句是:
UPDATE Payment
SET paymenttype = PAYMENT_TYPE,
paymentdate = TO_CHAR(sysdate,'DD/MON/YYYY'),
paymentstatus = v_paymentstatus
where paymentid = PAYMENT_ID;
您没有告诉它更新金额,因此触发器没有修改后的 :new
值 - 新旧值相同。您需要在更新中包括该列:
UPDATE Payment
SET paymenttype = PAYMENT_TYPE,
paymentdate = TO_CHAR(sysdate,'DD/MON/YYYY'),
paymentamount = amt_pay,
paymentstatus = v_paymentstatus
where paymentid = PAYMENT_ID;
TO_CHAR(sysdate,'DD/MON/YYYY')
看起来很奇怪 - table 列应该是日期而不是字符串,因此您不应该将该值转换为字符串;如果该列是日期,那么您将依靠客户端的 NLS 设置将其转换回来。如果您想忽略当前时间,则可以改为 TRUNC(sysdate)
。
您也不应该依赖过程主体中的 dbms_output
- 您无法控制调用它的人是否启用了输出,因此他们可能永远看不到问题。当您在触发器中引发异常时,您可以在其他错误的过程中执行相同的操作。