比如: emp表,
当新增一条数据的时候,进行与表中ename字段进行判断, 如果新增的数据ename在表中已经存在,则除主键外其他字段均与原数据相同,并插入.若没有相同的ename字段值,不做处理,直接插入
例如: 要创建一条empno为9988, ename为SMITH的数据,其他字段不写,取默认,经过触发器后,新增的数据为 [empno:9988, ename:SMITH, job:CLERK, mgr:7902, hiredate:17-DEC-80, sal: 800, comm: (null), deptno:20](仅仅empno不同,其余字段相同)
不知该如何写这样一个触发器,求大神给解答一下,如果有执行语句就最好不过了

解决方案 »

  1.   

    楼主这个需求,不妨考虑把 insert 换成 merge 语句,非常适合你现在的需求。merge into 的语法, 先百度一下,有问题再来追问。
      

  2.   

    非常感谢2楼解答,我先去搜索下merge的用法
      

  3.   


    create or replace trigger tri_insert_empyee
    after
    insert
    on emp
    for each row
    declare
    begin
        --当插入的时候执行
        if insert then
            merge into emp e
            using (
                        --搜索新插入数据(其中部分字段为空,以此筛选)
                        select * from emp where sal = null
                    ) ee
            on (
                --已两张表中empno相同,且工资e表中工资不为空作为条件
                e.ename = ee.ename and
                e.sal  != null
            )
            when matched then
                --当匹配时,对新增数据中的字段进行赋值
                update set (ee.sal = e.sal)
            when not matched then
                --不匹配情况下,则直接插入,未填写字段取空值(此处不确定,因为触发器时在执行插入之后触发,那么下面的插入操作是否就导致数据重复执行了?)
                insert (e.empno,e.ename,e.job,e.mgr,e.hiredate,e.sal,e.comm,e.deptno) values (ee.empno, ee.ename, ee.job, ee.mgr, ee.hiredate, ee.sal, ee.comm, ee.deptno);
        end if;
    end;报错:LINE/COL  ERROR
    --------- -------------------------------------------------------------
    3/8       PLS-00103: 出现符号 "INSERT"在需要下列之一时:  ( - + case mod new not    null <an identifier> <a double-quoted delimited-identifier>    <a bind variable> continue avg count current exists max min    prior sql stddev sum variance execute forall merge time    timestamp interval date    <a string literal with character set specification>    <a number> <a single-quoted SQL string> pipe    <一个带有字符集说明的可带引号的字符串文字>    <一个可带引号的 SQL 字符串> purge 
    错误: 查看编译器日志
      

  4.   


    前辈,请问4楼这样写,哪里出问题了,orcale报错实在有些看不懂,另外我这样写的思路是对的吗?
      

  5.   

    不是 merge 写到触发器中,而是用 merge 替换掉原来的 insert 语句,也就用不到触发器了。
      

  6.   


    实际是别人的数据通过insert导入到我的表中来,我无法控制,原本是要做个触发器,在对新导入过来的数据进行部分字段判断,我的表中如果存在相同的记录的时候,就把新导入的记录中的其他部分字段进行更新替换,看来merge对我的这个功能不太合适了.
      

  7.   

    嗯,看来不适用于这个 merge 语法。你这个只能考虑组合触发器了。大概思路如下:
    1、在 before  row 记录一下所有新插入的数据。
    2、在 after stmt 中处理所有重复数据、
      

  8.   

    直接BEFOR INSERT触发器就可以了吧先select * from table into 变量 where empname = :new.empname;
    然后:new.*** := 变量A;
          :new.*** := 变量B; 
    以此类推即可
      

  9.   

    最好empname这个字段做个索引,不然表的数据量大的话,这个trigger效率低的吓人