### Oracle 触发器实现详解 #### 一、Oracle 触发器概述 触发器是存储在数据库中的特殊类型的存储过程,它会在特定的数据库事件(如数据的插入、更新或删除)发生时自动执行。Oracle 数据库支持多种类型的触发器,包括 `BEFORE` 和 `AFTER` 触发器,以及对于 `INSERT`、`UPDATE` 和 `DELETE` 操作的触发器。 #### 二、触发器示例解析 在提供的代码片段中,展示了两个触发器的创建语句:`AddTrainDayMove` 和 `EditTrainMonthMove`。我们将逐一分析这两个触发器的功能及其实现细节。 ##### 2.1 AddTrainDayMove 触发器 该触发器在 `train_day_move` 表上定义,并且是在插入新记录之前 (`before insert`) 执行。其主要功能包括: - **统计月份移动量**:计算某列车在指定年份和月份内的总移动次数。 - **更新月度统计数据**:如果月份数据已存在,则更新;如果不存在,则插入新的月度统计数据。 - **更新列车装配表**:更新列车装配表中的总移动量。 **具体实现**: ```sql CREATE OR REPLACE TRIGGER AddTrainDayMove BEFORE INSERT ON train_day_move FOR EACH ROW DECLARE t_month_move INTEGER; t_after_make_move INTEGER; c_month INT; c_day INT; BEGIN -- 统计当前月份的移动次数 SELECT COUNT(*) INTO c_day FROM train_day_move WHERE month = :new.month AND year = :new.year AND train_id = :new.train_id; IF c_day > 0 THEN -- 计算当前月份的总移动次数 SELECT SUM(t.day_move) INTO t_month_move FROM train_day_move t WHERE t.month = :new.month AND t.year = :new.year AND t.train_id = :new.train_id; -- 获取当前列车的后续制造移动次数 SELECT t.after_make_move INTO t_after_make_move FROM train_day_move t WHERE t.train_id = :new.train_id AND record_state = '1' AND train_type = :new.train_type AND train_no = :new.train_no; -- 更新当前行的移动次数 :new.month_move := :new.day_move + t_month_move; :new.after_make_move := :new.day_move + t_after_make_move; -- 更新 train_day_move 表中的记录状态 UPDATE train_day_move SET record_state = '0' WHERE train_id = :new.train_id AND record_state = '1'; -- 更新 train_fitting 表中的总移动量 UPDATE train_fitting SET all_move = all_move + :new.day_move WHERE id = (SELECT fitting_id FROM Train_Assemble WHERE train_type = :new.train_type AND train_no = :new.train_no AND record_state = '1' AND assem_or_unassem = '1'); -- 统计当前月份是否存在数据 SELECT COUNT(*) INTO c_month FROM train_month_move WHERE month = :new.month AND year = :new.year AND train_id = :new.train_id; -- 如果月份数据已存在,则更新 IF c_month > 0 THEN UPDATE train_month_move t SET t.month_Move = :new.month_move, t.month_Correct_Move = :new.month_move, t.after_Make_Move = :new.after_make_move WHERE t.train_id = :new.train_id AND t.year = :new.year AND t.month = :new.month; END IF; -- 如果月份数据不存在,则插入 IF c_month = 0 THEN INSERT INTO train_month_move (id, train_id, year, month, month_move, month_correct_move, after_make_move, train_type, train_no) VALUES (:new.id, :new.train_id, :new.year, :new.month, :new.month_move, :new.month_move, :new.after_make_move, :new.train_type, :new.train_no); END IF; END IF; -- 如果当前月份没有数据,则直接设置移动次数 IF c_day = 0 THEN :new.month_move := :new.day_move; :new.after_make_move := :new.day_move; END IF; END AddTrainDayMove; ``` ##### 2.2 EditTrainMonthMove 触发器 该触发器定义在 `train_month_move` 表上,并且是在更新记录前 (`before update`) 执行。其主要功能为更新 `train_month_move` 表中的某些字段。 **具体实现**: 由于提供的代码片段不完整,无法给出完整的触发器实现。但从其结构来看,可以推测该触发器的主要目的是在更新 `train_month_move` 表中的记录时进行一些额外的数据处理或验证。 ### 三、总结 通过以上分析可以看出,触发器是数据库中非常强大的工具,可以用来实现复杂的数据完整性规则和业务逻辑。在设计触发器时需要注意避免循环引用和死锁等问题,同时也要确保触发器逻辑的正确性和效率。在实际应用中,合理地利用触发器可以帮助我们更高效地管理数据并确保数据的一致性。
before insert on train_day_move
for each row
declare
t_month_move integer;
t_after_make_move integer;
c_month int;
c_day int;
begin
select count(*)
into c_day
from train_day_move
where month = :new.month
and year = :new.year
and train_id = :new.train_id;
if c_day > 0 then
/*机车当月走行*/
select sum(t.day_move)
into t_month_move
from train_day_move t
where t.month = :new.month
and t.year = :new.year
and t.train_id = :new.train_id;
/*机车新造走行*/
select t.after_make_move
into t_after_make_move
from train_day_move t
where t.train_id = :new.train_id
- 粉丝: 0
- 资源: 18
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助