在oracle中执行立即插入时,异常剂量不起作用

时间:2017-06-27 05:29:46

标签: oracle plsql

我在执行立即插入语句异常部分时遇到了一些问题。

我的表格query_tb包含两列(DEPTSOURCE_VALUE

该列包含以下数据

秘书

select a.empno,a.ename,a.job,a.mgr,a.hiredate,b.deptno,b.dname,b.loc 
            from emp a,dept b where a.deptno=b.deptno and a.empno= '#V_GCIF#'

SALESMAN

select e.empno,e.ename,e.job,d.deptno,d.dname,d.loc from emp e,dept 
            d where e.deptno=d.deptno and e.empno= '#V_GCIF#'

MANAGER

select a.empno,a.ename,a.job,b.deptno,b.dname,b.loc from employee 
             a,department b where a.deptno=b.deptno and a.empno= '#V_GCIF#'

ADMIN

select a.empno,a.ename,a.job,b.deptno,b.dname,b.loc from employee 
            a,department b where a.deptno=b.deptno and a.empno= '#V_GCIF#'

如果我传递了empno表中保留的正确emp,它运行正常。但是如果我传递了不正确的empno(没有数据),那么异常部分就无效了。

create or replace
PROCEDURE test_emp_sp(
    p_id IN VARCHAR2)
AS
  CURSOR rec
  IS
    SELECT dept,
      source_value
    FROM query_tb;
  v_query  VARCHAR2(1000);

BEGIN

  FOR rec IN
  (SELECT dept,source_value FROM query_tb
  )
  LOOP
 IF rec.dept='CLERK' THEN
 v_query :=REPLACE(rec.source_value,'#V_GCIF#',p_id);

 EXECUTE IMMEDIATE 'INSERT INTO emp_tb (empno,ename,job,mgr,hiredate,deptno,dname,loc) ('||v_query|| ')';

 dbms_output.put_line(v_query||'    inserted');

ELSE

 v_query:=REPLACE(rec.source_value,'#V_GCIF#',p_id);

 EXECUTE IMMEDIATE 'INSERT INTO emp_tb (empno,ename,job,deptno,dname,loc) ('||v_query||')';

 dbms_output.put_line(v_query||'    inserting others');

  END IF;

  END LOOP;

 commit;

EXCEPTION

WHEN others THEN
  dbms_output.put_line('No data Found...');

END;

4 个答案:

答案 0 :(得分:0)

异常不起作用,因为没有异常。 如果SELECT返回NULL,那么0行将是INSERT。 例如:

insert into t1(c1)
select 100 from dual where 1=0;

结果:插入了0行。

答案 1 :(得分:0)

insert into ... select from.. 不会引发no_data_found异常。它只会插入0条记录。

要测试是否插入了任何记录,可以在insert语句后使用SQL%ROWCOUNT。

execute immedate 'INSERT...;

if SQL%ROWCOUNT=0 
then
    dbms_output.put_line('no records inserted');
else
  ...
end if;

此外,您可能需要考虑将#V_GCIF#更改为可用作绑定变量的内容,例如:P_ID。

您可以跳过replace语句并将execute immediate更改为:

execute immediate 'INSERT INTO ...'||v_query
using p_id;

这会将p_id的值绑定到语句中的:p_id。

答案 2 :(得分:0)

那是因为你没有运行select命令,它是一个insert命令(insert select),这意味着如果select赢了&#39 ; t返回行,它不会插入任何内容,也不会抛出任何错误。您应该检查insert命令是否影响了任何行。在Oracle中执行此操作的方法是在执行后立即检查SQL%ROWCOUNT,如果它变为0,则表明您的工作会引发异常。它会是这样的:

DECLARE
   customException EXCEPTION;
   PRAGMA EXCEPTION_INIT( customException, -20001 );

....
BEGIN
     EXECUTE IMMEDIATE 'INSERT INTO emp_tb (empno,ename,job,mgr,hiredate,deptno,dname,loc) 
                       ('||v_query|| ')';
    IF (SQL%ROWCOUNT) = 0 then
       raise_application_error( -20001, 'This is a custom error' );
    end if;
EXCEPTION
   WHEN customException THEN
      dbms_output.put_line('No data Found...');  
END;

很长一段时间没有在Oracle PLSql中编程所以在提供的代码上的某些东西可能无法编译,但它在互联网上的所有内容都可以看到它并且你会很好。

答案 3 :(得分:-1)

这里最基本的是适当地捕获错误,以便您能够追溯。在这里,我已经使用loggers和EXCEPTION处理程序jsut来检查错误。我也放了一个RAISE_APPLICATION_ERROR。在snipet中做了一些修改。希望它有所帮助。

PS:没有检查语法,因为我现在没有工作区。

CREATE OR REPLACE
PROCEDURE test_emp_sp(
    p_id IN VARCHAR2)
AS
--Not needed
--  CURSOR rec
--  IS
--    SELECT dept,
--      source_value
--    FROM query_tb;
--Not needed
  v_query VARCHAR2(1000);
BEGIN
  FOR rec IN
  (SELECT dept,source_value FROM query_tb
  )
  LOOP
    IF rec.dept='CLERK' THEN
      v_query :=REPLACE(rec.source_value,'#V_GCIF#',p_id);
      BEGIN
      EXECUTE IMMEDIATE 'INSERT INTO emp_tb (empno,ename,job,mgr,hiredate,deptno,dname,loc) ('||v_query|| ')';
      dbms_output.put_line(v_query||'    inserted');
      EXCEPTION WHEN OTHERS THEN
      dbms_output.put_line(' Error while inserting data in emp_tab for Clerk--> '||SQLCODE||'---'||SQLERRM);
      END;
    ELSE
      v_query:=REPLACE(rec.source_value,'#V_GCIF#',p_id);
      BEGIN
      EXECUTE IMMEDIATE 'INSERT INTO emp_tb (empno,ename,job,deptno,dname,loc) ('||v_query||')';
      dbms_output.put_line(v_query||'    inserting others');
      EXCEPTION WHEN OTHERS THEN
      dbms_output.put_line(' Error while inserting data in emp_tab for other then clerk --> '||SQLCODE||'---'||SQLERRM);
      END;
    END IF;
  END LOOP;
  COMMIT;
EXCEPTION
WHEN OTHERS THEN
  RAISE_APPLICATION_ERROR(-20001,'Error occurred in the plsql block',TRUE);
END;
/