【问题标题】:Having trouble creating trigger that updates column based on variable无法创建基于变量更新列的触发器
【发布时间】:2018-04-26 14:11:14
【问题描述】:

我正在尝试为一个类创建一个触发器,该触发器根据商品退回的延迟天数或提前天数更新客户余额。我有一个包含到期日期和返回日期的章程表,触发器设计为仅在更新返回日期时触发。然后触发器获取返回日期和到期日期之间的差异,并将该值存储到变量中。我有一系列 if else 语句来确定该项目是迟到还是早退,然后将天数乘以滞纳金或早期奖金。然后它将客户表中的客户余额更新为费用变量的值。 Oracle 说我的 end 语句有语法错误,我不确定是什么问题。

CREATE OR REPLACE TRIGGER Fee_Trigger
AFTER UPDATE ON CHARTER
FOR EACH ROW 
WHEN ((:NEW.Return_Date <> :OLD.Return_Date AND :NEW.Return_Date IS NOT 
NULL))
DECLARE
Fee NUMBER; 
BEGIN 
Fee := (:NEW.Return_Date - Due_Date); 
IF Fee > 0 THEN Fee := (Fee * 75) ;
ELSE IF Fee < 0 THEN Fee := (Fee * 25);
ELSE IF Fee = 0 THEN FEE := Fee;
END IF;
UPDATE CUSTOMER 
SET Customer_Balance = Fee
WHERE CustomerID = :NEW.CustomerID
END;

【问题讨论】:

  • UPDATE 语句不以分号结尾。
  • 您的代码在幼稚的阅读中毫无意义。两个日期之间的差异将是一个间隔类型。将区间类型分配给名为 customer_balance 的列是非常可疑的。

标签: sql oracle plsql database-trigger


【解决方案1】:

有一些小的格式错误。也可以使用以下方法:

CREATE OR REPLACE TRIGGER Fee_Trigger
AFTER UPDATE ON CHARTER
FOR EACH ROW 
WHEN ((NEW.Return_Date <> OLD.Return_Date AND NEW.Return_Date IS NOT NULL))
DECLARE
 Fee NUMBER; 
BEGIN 
 Fee := :NEW.Return_Date - :NEW.Due_Date; 

 IF    Fee > 0 THEN Fee := (Fee * 75); 
 ELSIF Fee < 0 THEN Fee := (Fee * 25);
 ELSIF Fee = 0 THEN Fee := Fee;
 END IF;

 UPDATE CUSTOMER 
    SET Customer_Balance = Fee
  WHERE CustomerID = :NEW.CustomerID;

END;

遇到以下问题:

  • Due_date 未定义(可以使用:OLD.Due_Date:NEW.Due_Date
  • 应该使用ELSIF 而不是ELSE IF
  • UPDATE 语句应以 semicolon 结尾。
  • 删除OLD 之前的colonsWHEN 语句中的NEW

【讨论】:

  • 感谢您的帮助,我没有注意到缺少的分号并忘记了它是 elsif。但是,现在当我尝试编译时,Oracle 给了我一个错误,说在 When 子句中无效使用绑定变量。此外,我认为我不需要声明 Due_Date,因为在插入 return_date 之前,该日期已经在章程表中预定义。你能解释一下为什么我不应该使用整数的日期差来更新吗?通过使用差异,我得到了迟到/早的天数,并将它们乘以相应的费用/退款。
  • @Vanir 好的,背后的逻辑是你的选择。我针对其他问题进行了编辑(我将 Due_Date 转换为:NEW.Due_Date,因为您告诉 CHARTER 有该列)。
【解决方案2】:

我建议在 UPDATE 语句中用 CASE 表达式替换 IF/ELSIF 语句:

CREATE OR REPLACE TRIGGER Fee_Trigger
  AFTER UPDATE ON CHARTER
  FOR EACH ROW 
  WHEN ((:NEW.Return_Date <> :OLD.Return_Date AND :NEW.Return_Date IS NOT NULL))
DECLARE
  Due_Date                      DATE := TRUNC(SYSDATE); -- initialization as an example value.
  nDays_between_return_and_due  NUMBER;
BEGIN
  nDays_between_return_and_due := TRUNC(:NEW.Return_Date - Due_Date);

  UPDATE CUSTOMER 
    SET Customer_Balance = CASE
                             WHEN nDays_between_return_and_due > 0 THEN  -- Returned late
                               nDays_between_return_and_due * 75
                             WHEN nDays_between_return_and_due < 0 THEN  -- Returned early
                               nDays_between_return_and_due * 25
                             ELSE  -- Returned on time
                               0
                           END
    WHERE CustomerID = :NEW.CustomerID;
END FEE_TRIGGER;

祝你好运。

【讨论】:

    猜你喜欢
    • 2017-04-26
    • 1970-01-01
    • 1970-01-01
    • 2018-06-05
    • 1970-01-01
    • 2022-01-21
    • 2020-08-24
    • 2019-05-03
    • 1970-01-01
    相关资源
    最近更新 更多