Oracle 如何将PL/SQL本地定义的类型与表运算符一起使用
我正在开发一个触发器,用于更新记录部门及其工资总额的表格。每次更新EMP表时。触发器将更新此表。为了避免突变表的错误,我实现了一个复合触发器类型触发器 我把你的实现放在这里:Oracle 如何将PL/SQL本地定义的类型与表运算符一起使用,oracle,plsql,Oracle,Plsql,我正在开发一个触发器,用于更新记录部门及其工资总额的表格。每次更新EMP表时。触发器将更新此表。为了避免突变表的错误,我实现了一个复合触发器类型触发器 我把你的实现放在这里: 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
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,我可以使用本地定义类型的表运算符。正如本文所讨论的
编译器返回给我的错误如下:
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
正如劳德克所评论的那样,维护部门列表和总薪酬的一种非常简单的方法是:
Create Or Replace View salario_departamentos_view As
Select deptno, Sum(sal) As sal_tot From emp
Group By deptno;
此解决方案的妙处在于,数据始终与EMP表完美协调,而且即使对于SQL技能最低的人来说,也很容易理解。是否需要使用集合?如果不是,那么一个简单的行级触发器应该可以工作,如下所示:
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;
/
新旧值的单独update语句处理更新行可能包含更改的部门编号的情况。尝试将类型定义更改为类型t_DeptToUpdate IS TABLE of number或类型t_DeptToUpdate IS TABLE of EMP.DEPTNO%类型。祝你好运。我有点好奇,为什么你要经历一个触发器更新一个表的麻烦,而你可以创建一个非常简单和快速的视图来为你做这件事,并且总是最新的。也许我遗漏了一些东西,你也可以试试DeTutoupDeD的DePtNo成员,而不是DeTtNo。也许您必须将MERGE转换为INSERT和UPDATE语句。我的理解是,即使在12c中,类型也必须在包规范中定义。如果在包体或触发器中声明类型,则无法工作。感谢您的回复。在建议的练习中,我必须使用触发器。我知道理想的做法是使用视图。谢谢,这太完美了