【问题标题】:Reduce the value of a vehicle every month每个月减少一辆车的价值
【发布时间】:2014-12-06 09:19:57
【问题描述】:

我要做的是减少“车辆”表中每辆车的价值,以便当日期超过“上次更新”值一个月时,“价值”列减少 2.5%。触发器应在登录数据库后运行。问题是,一个 DBA 可能不会每天都登录数据库,所以如果距离上次登录已经过去了六个月,触发器将循环遍历,将值减少 2.5% 并执行 ADD_MONTHS(LastUpdate, 1)。

计算值的函数代码是:

REATE OR REPLACE FUNCTION  fn_Vehicle_Value
(VehicleNumber IN NUMBER,
VehicleValue IN OUT NUMBER)
RETURN NUMERIC
IS
BEGIN 
VehicleValue := VehicleValue - (VehicleValue * 0.025);
RETURN VehicleValue;
END;
/

这是我创建系统触发器的尝试:

CREATE OR REPLACE TRIGGER tg_VehicleDepreciate
AFTER LOGON ON DATABASE
IS
CURSOR vehicle_cur IS SELECT "VALUE", LastUpdate FROM Vehicle;
BEGIN
FOR vehicle_rec IN vehicle_cur LOOP

      WHILE LastUpdate < SYSDATE LOOP
           LastUpdate."Value" := fn_Vehicle_Update("VALUE");

            UPDATE Vehicle
             SET LastUpdate := ADD_MONTHS(LastUpdate, 1)
              WHERE Vehicle# = vehicle_cur.Vehicle#;

      END LOOP;


EXIT WHEN vehicle_cur%NOTFOUND;
END LOOP
END;
/

据我所知,我的功能是正确的。但是触发器没有编译并产生以下错误报告:

错误报告 - ORA-04079: 无效的触发器规范 04079. 00000 - “无效的触发规范” *原因:create TRIGGER 语句无效。 *操作:检查语句的语法是否正确。

我猜这是一个语法错误,但也可能是一个我无法解决的逻辑错误。

【问题讨论】:

  • 为什么不创建一个“即时”计算的视图呢?我认为不需要为可以从现有数据派生的内容创建触发器(您需要在 vehicle 表中添加“开始日期”或“创建日期”)
  • 这是一个单一的任务,我必须完全按照我被告知的去做。导师告诉我们需要使用函数和触发器。
  • 通过AFTER LOGON ON DATABASE 触发器触发更新听起来有点愚蠢。例如,为什么不创建一个SCHEDULER JOB 并在每个午夜运行一次?
  • 您的导师是否建议您使用“触发器”或AFTER LOGON ON DATABASE 触发器?

标签: sql oracle function plsql triggers


【解决方案1】:

SHOW ERRORS 编译触发器后会显示所有错误。

这里有几个..
1) 在更新中,它只是SET somecolumn = Somevalue
2) 当与 FOR 循环一起使用时,oracle 会隐式打开游标并关闭。
3) 使用 FOR 循环后,获取的结果应该使用类似.. Forloopvariable.column-name
4) 将Vehicle# 添加到您的光标。
5) 添加V_date逻辑。

CREATE OR REPLACE TRIGGER tg_VehicleDepreciate
AFTER LOGON ON DATABASE
IS
CURSOR vehicle_cur IS SELECT "VALUE", LastUpdate ,Vehicle# FROM Vehicle;
V_date DATE;
BEGIN
FOR vehicle_rec IN vehicle_cur LOOP

      V_date := vehicle_rec.LastUpdate;

      WHILE   V_date < SYSDATE LOOP
          /* what are you trying here? */
           ---vehicle_rec."Value" := fn_Vehicle_Update("VALUE");

            UPDATE Vehicle
             SET LastUpdate = ADD_MONTHS(LastUpdate, 1)
              WHERE Vehicle# = vehicle_rec.Vehicle#;

             V_date := ADD_MONTHS( V_date,1);

      END LOOP;

END LOOP
END;
/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-07
    • 2018-04-01
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 2022-07-07
    • 1970-01-01
    相关资源
    最近更新 更多