Plsql 更新触发器PL/SQL Oracle
我有一个具有以下结构的表:Plsql 更新触发器PL/SQL Oracle,plsql,oracle11g,triggers,Plsql,Oracle11g,Triggers,我有一个具有以下结构的表: create table treballa ( code varchar2(4), name varchar2(20), director varchar2(4), department number, salary int, primary key (code), foreign key (director) references treballa(code) ) 我需要创建一个触发器来检查更新员工的部门号,该部门所有员工之间的总工资是否不超
create table treballa (
code varchar2(4),
name varchar2(20),
director varchar2(4),
department number,
salary int,
primary key (code),
foreign key (director) references treballa(code)
)
我需要创建一个触发器来检查更新员工的部门号,该部门所有员工之间的总工资是否不超过10000,但我真的不知道该怎么做。。。你能帮帮我吗?多谢各位
编辑:
结束编辑/
更新时出错:
[42000][4091]ORA-04091:表特殊。特雷巴拉正在变异,
触发器/函数可能看不到它ORA-06512:at
“SPECIAL.CONTROLSALARIDEPT”,第14行ORA-04088:执行期间出错
触发器'SPECIAL.CONTROLSALARIDEPT'的
对不起,我对甲骨文很陌生,我需要这个触发器的帮助,我不知道我现在做的是否正确。。。。触发器的第一部分“如果插入”工作正常,问题在于更新…尝试复合触发器:
CREATE OR REPLACE TRIGGER compound_trigger_name
FOR INSERT OR UPDATE OF salary ON treballa
COMPOUND TRIGGER
TYPE Departments_t IS TABLE OF treballa.department%TYPE INDEX BY varchar2(100);
Departments Departments_t;
BEFORE EACH ROW IS
BEGIN
-- collect updated or inserted departments
Departments( :new.department ) := :new.department;
END BEFORE EACH ROW;
AFTER STATEMENT IS
sum_sal NUMBER;
BEGIN
-- for each updated department check the restriction
FOR dept IN Departments.FIRST .. Departments.LAST
LOOP
SELECT sum(salary) INTO sum_sal FROM treballa WHERE department = dept;
IF sum_sal > 1000 THEN
raise_application_error(-20123, 'The total salary for department '||dept||' cannot exceed 1000');
END IF;
END LOOP;
END AFTER STATEMENT;
END compound_trigger_name;
/
TYPE Departments_t IS TABLE OF treballa.department%TYPE INDEX BY varchar2(100);
Departments Departments_t;
==========编辑-一些问题和答案=================
Q:为什么会发生变异表错误?
答:这在文档中有描述:
触发对变异表的限制
变异表是一个表 由UPDATE、DELETE或INSERT语句或 可能会因删除级联效应而更新的表 约束 发出触发语句的会话无法查询或 修改变异表。此限制可防止触发器 看到一组不一致的数据 此限制适用于对每行使用 条款不考虑在而不是触发器中修改的视图 变异 当触发器遇到变异表时,会发生运行时错误, 触发器主体和触发器语句的效果将被滚动 返回,控件将返回给用户或应用程序。(你可以使用 复合触发器以避免突变表错误 有关详细信息,请参阅使用复合触发器以避免表发生变化 错误。)
Q:如何避免变异表错误?
答:文档建议使用复合触发器,请参见:
使用复合触发器以避免改变可以使用的表错误 避免突变表错误的复合触发器(ORA-04091) 在变异表的触发器限制中描述
Q:什么是复合触发器及其工作原理?
答:这是一个庞大的主题,请参阅此处的文档:
简言之:这是一种特殊的触发器,它可以将四种不同类型的触发器组合成一个声明:
BEFORE statement
、BEFORE for each row
、AFTER for each row
和AFTER statant
。这使得实现一些场景变得更容易,其中需要将一些数据从一个触发器传递到另一个触发器。请研究以上链接以了解更多详细信息
问:但部门(:new.department):=:new.department;?实际做什么 答:此声明将部门号存储到关联数组中。
此数组在复合触发器的声明性部分声明:
CREATE OR REPLACE TRIGGER compound_trigger_name
FOR INSERT OR UPDATE OF salary ON treballa
COMPOUND TRIGGER
TYPE Departments_t IS TABLE OF treballa.department%TYPE INDEX BY varchar2(100);
Departments Departments_t;
BEFORE EACH ROW IS
BEGIN
-- collect updated or inserted departments
Departments( :new.department ) := :new.department;
END BEFORE EACH ROW;
AFTER STATEMENT IS
sum_sal NUMBER;
BEGIN
-- for each updated department check the restriction
FOR dept IN Departments.FIRST .. Departments.LAST
LOOP
SELECT sum(salary) INTO sum_sal FROM treballa WHERE department = dept;
IF sum_sal > 1000 THEN
raise_application_error(-20123, 'The total salary for department '||dept||' cannot exceed 1000');
END IF;
END LOOP;
END AFTER STATEMENT;
END compound_trigger_name;
/
TYPE Departments_t IS TABLE OF treballa.department%TYPE INDEX BY varchar2(100);
Departments Departments_t;
与复合触发器相关的文档说明:
可选的声明性部分(第一部分)声明变量和
计时点段可以使用的子程序。当触发器
激发时,声明性部分在任何计时点节之前执行
本节中声明的变量和子程序
触发语句持续时间
上面的意思是,部门
变量仅在整个处理开始时,触发器触发后初始化一次。“触发语句持续时间”意味着该变量在触发器完成后被销毁。此语句:
Departments(:new.department):=:new.department;
在关联数组中存储一个部门编号。它位于每行部分之前的,然后对由update/insert语句更新(或插入)的每一行执行。
:new
和:old
都是伪记录,您可以在这里找到更多关于它们的信息:
简而言之::new.department
为当前更新的行(更新后的值)检索department
列的新值,而:old.department
为该列提供旧值(更新前).
当触发器选择所有更新的部门(在一个FOR-LOOP中)时,此集合稍后将用于AFTER语句中,对于每个部门,触发选择SUM(salary)…
,然后检查此总和是否小于1000
考虑一个简单的更新:<代码>更新TrBura设置薪水=工资+ 10 < /代码>。这是一个更新语句,但同时更改多行。我们的触发器的执行顺序如下:
更新状态被触发:update treballa SET salary=salary+10
触发器的声明性部分被执行,即:Departments
变量被初始化
在执行每一行之前
部分,分别针对每个更新的行-更新的行数相同。在这里,我们从更改的行中收集所有部门
AFTER语句
部分被执行。此时表已经更新-所有行都已经有了新的更新工资。我们循环遍历保存在部门
中的部门,并检查每个部门的工资总和是否小于或等于1000。如果这些部门中的任何一个的工资总和大于1000,则会出现错误否则,触发器将完成,更新将完成(但无论如何都需要提交这些更改)
Q:什么是关联数组,为什么只是t