我正在开发一个触发器,可以更新记录部门的表格以及工资总额。每次更新EMP表。触发器更新此表。为了避免突变表的错误,我实现了一个“COMPOUND TRIGGER”类型的触发器。
我在这里实施您的实施:
CREATE OR REPLACE TRIGGER EJERCICIO_27
FOR INSERT OR UPDATE OR DELETE ON EMP
COMPOUND TRIGGER
TYPE t_DeptToUpdate IS TABLE OF NUMBER(2,0);
deptToUpdate t_DeptToUpdate;
-- AFTER EACH ROW Section:
AFTER EACH ROW IS
BEGIN
IF NOT :OLD.DEPTNO MEMBER OF deptToUpdate THEN
deptToUpdate.EXTEND;
deptToUpdate(deptToUpdate.LAST) := :OLD.DEPTNO;
END IF;
END AFTER EACH ROW;
-- AFTER STATEMENT Section:
AFTER STATEMENT IS
BEGIN
DBMS_OUTPUT.PUT_LINE('SE ACTUALIZAN UN TOTAL DE: ' || deptToUpdate.COUNT);
MERGE INTO SALARIO_DEPARTAMENTOS SD USING (
SELECT DEPTNO, NVL(SUM(SAL), 0) AS SUM_TOTAL FROM EMP
WHERE DEPTNO IN (SELECT * FROM TABLE(deptToUpdate))
GROUP BY DEPTNO
) D
ON (SD.DEPTNO = D.DEPTNO)
WHEN MATCHED THEN
UPDATE SET
SAL_TOT = D.SUM_TOTAL
WHERE SD.DEPTNO = D.DEPTNO
WHEN NOT MATCHED THEN
INSERT (DEPTNO, SAL_TOT)
VALUES(D.DEPTNO, D.SUM_TOTAL);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR : ' || SQLCODE || 'MENSAJE: ' || SQLERRM);
END AFTER STATEMENT;
END;
/
使用集合作为查询MERGE语句的源时遇到的问题。我理解在Oracle 12c中(我使用的是Oracle 12c R2 Enterprise)我可以使用TABLE运算符和本地定义的类型。正如本文Using the TABLE Operator with Locally Defined Types in PL/SQL中所讨论的那样。
编译器返回的错误恰好是:
LINE/COL ERROR
-------- -----------------------------------------------------------------
20/5 PL/SQL: SQL Statement ignored
22/40 PL/SQL: ORA-22905: no se puede acceder a las filas de un elemento de tabla no anidada
22/46 PLS-00642: tipos de recopilación local no permitidos en sentencias SQL
有人可以告诉我使用什么方法而不必在原理图中创建任何类型?提前谢谢。
错误消息的翻译:
ORA-22905: Rows of a non-nested table element can not be accessed
PLS-00642: Local collection types not allowed in SQL statements
答案 0 :(得分:1)
正如LauDec评论的那样,维护一个部门和总薪水清单的一种非常直接的方式是这样的观点:
Create Or Replace View salario_departamentos_view As
Select deptno, Sum(sal) As sal_tot From emp
Group By deptno;
这个解决方案的优点在于数据始终与EMP表格完美协调,并且即使对于具有最低SQL技能的人来说,它也非常容易理解。
答案 1 :(得分:1)
您是必需使用收藏品吗?如果没有,那么似乎一个简单的行级触发器应该可以工作,如下所示:
Create Or Replace Trigger emp_trig
After Insert Or Update Or Delete On emp
For Each Row
Begin
-- Subtract old salary from old department
Update department_salary ds
Set ds.tot_salary = ds.tot_salary - :old.salary
Where ds.dept = :old.dept;
If Inserting Or Updating Then
-- Add new salary to new department
Update department_salary ds
Set ds.tot_salary = ds.tot_salary + :new.salary
Where ds.dept = :new.dept;
If SQL%Rowcount = 0 Then
Insert Into department_salary (dept, tot_salary) Values(:new.dept, :new.salary);
End If;
End If;
End;
/
旧值和新值的单独更新语句处理更新的行可能包含更改的部门编号的情况。