【问题标题】:Oracle Trigger How to get Inserted value's parameterOracle触发器如何获取插入值的参数
【发布时间】:2018-05-20 10:26:02
【问题描述】:

我在研究 Oracle 数据库的触发器时有一个问题。

首先,我创建了两个如下表:

**[Employee]**
(empno NUMBER, VARCHAR2 (20), deptno NUMBER, salary NUMBER)
**[Department]**
(deptno NUMBER, dname VARCHAR2 (20))

Employee deptno 指的是部门的deptno。

我要创建的触发器是用deptno计算数据的平均工资,比如inserted deptno。

例如,假设我运行以下代码。

INSERT INTO employee values (1000, 'PAUL', 10, 4000);

那么触发器想要有以下输出:

Department [10]'s average of Salary = <avg (salary)>

但我不知道如何在触发器中传递插入行的参数。

有人有什么好办法吗?

【问题讨论】:

  • 我知道您只是在学习基础知识,但在创建任何触发器之前请三思,不要轻易创建它们。它们可能非常昂贵(以及其他陷阱)。例如,如果您在此表中有 1000 万行,您真的想在每次插入、更新或删除行时对所有行运行聚合函数吗?在大多数情况下,如果可以避免触发器,我会避免它。这绝对不是触发器的情况。
  • 谢谢。我会熟悉你的建议。
  • 这是来自Tom Kyte 的好读物,它解释了我谈到的陷阱的更多信息。
  • 你是什么意思,“触发器将有以下输出”?输出到哪里,用于什么目的?

标签: oracle triggers insert


【解决方案1】:

我意识到如果我在触发器中使用 AFTER INSERT 关键字,我会收到“ORA-04091”错误,因为表的内容正在更改。所以我发现我必须在插入之前使用才能得到结果。 这不是正确的方法,但我能够表达我想要的输出。

这很简单。在更改表之前(在插入关键字之前),我将列的总和存储在变量中以获得平均值。 然后使用 ':NEW' 关键字将新值添加到变量中。

当我使用此方法时,我没有收到“ORA-04091”错误,因为该表仍在更改之前。

感谢很多人,我发现这不是在触发器中编写的好方法。 但是,我正在考虑这个问题,并且学习了很多内部操作,例如触发器的成本以及何时调用它们。

再次感谢所有回答者。

【讨论】:

    【解决方案2】:

    将其作为触发器实现是没有意义的。这只是一个简单的 SQL 查询:

    select deptno ,avg(salary)
    from employee
    group by deptno
    

    【讨论】:

    • 对不起。但我想将其打印为触发器。
    • 你可能会质疑我为什么使用这种方法,但我只想知道如何。我不只是在寻找一种实用的方法。
    • 您不能从触发器“打印”。当你有 10 个并发更新时会发生什么?
    • 我所说的“打印”是指 DBMS_OUTPUT.PUT_LINE()。当我简单地计算整体平均值而不使用任何其他参数时,我可以使用 AFTER INSERT 输出。
    【解决方案3】:

    Trigger 不是此类事情的最佳场所,但可以通过compound trigger 完成:

    create or replace trigger avg_dept_salary for insert on employee compound trigger
    
      type tb_num is table of number;
      v_depts tb_num := tb_num();
      v_sum number;
    
    before each row is 
      begin
        if :new.deptno not member of v_depts then
          v_depts.extend();
          v_depts(v_depts.count()) := :new.deptno;
        end if;
      end before each row;
    
    after statement is
      begin
        for i in 1..v_depts.count() loop
          select avg(salary) into v_sum from employee where deptno = v_depts(i);
          dbms_output.put_line('Department '||v_depts(i)||' average salary: '||v_sum);
        end loop;
      end after statement;
    
    end;
    

    测试:

    insert into employee 
      select 1001, 'PAUL', 10, 1000 from dual union all
      select 1002, 'ANNE', 10, 1700 from dual union all
      select 1003, 'MARY', 10,  900 from dual union all
      select 1004, 'JOHN', 20, 1200 from dual;
    

    每个受影响部门的输出:

    Department 10 average salary: 1900
    Department 20 average salary: 1200
    

    【讨论】:

    • 谢谢!我会尽快尝试。
    • 我尝试了你的源代码,但我收到一条错误消息 - ORA-04091: table employee is mutating, trigger/function may not see it.
    猜你喜欢
    • 1970-01-01
    • 2012-02-08
    • 2017-12-26
    • 2019-01-22
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 2018-04-11
    相关资源
    最近更新 更多