CREATE OR REPLACE PROCEDURE copy ( 
     source      IN VARCHAR2, 
     destination IN VARCHAR2) IS 
     id_var             NUMBER; 
     name_var           VARCHAR2(30); 
     birthdate_var      DATE; 
     source_cursor      INTEGER; 
     destination_cursor INTEGER; 
     ignore             INTEGER; 
  BEGIN 
 
  -- Prepare a cursor to select from the source table: 
     source_cursor := dbms_sql.open_cursor; 
     DBMS_SQL.PARSE(source_cursor, 
         'SELECT id, name, birthdate FROM ' || source, 
          DBMS_SQL.native); 
     DBMS_SQL.DEFINE_COLUMN(source_cursor, 1, id_var); 
     DBMS_SQL.DEFINE_COLUMN(source_cursor, 2, name_var, 30); 
     DBMS_SQL.DEFINE_COLUMN(source_cursor, 3, birthdate_var); 
     ignore := DBMS_SQL.EXECUTE(source_cursor); 
 
  -- Prepare a cursor to insert into the destination table: 
     destination_cursor := DBMS_SQL.OPEN_CURSOR; 
     DBMS_SQL.PARSE(destination_cursor, 
                  'INSERT INTO ' || destination || 
                  ' VALUES (:id_bind, :name_bind, :birthdate_bind)', 
                   DBMS_SQL.native); 
 
  -- Fetch a row from the source table and insert it into the destination table: 
     LOOP 
       IF DBMS_SQL.FETCH_ROWS(source_cursor)>0 THEN 
         -- get column values of the row 
         DBMS_SQL.COLUMN_VALUE(source_cursor, 1, id_var); 
         DBMS_SQL.COLUMN_VALUE(source_cursor, 2, name_var); 
         DBMS_SQL.COLUMN_VALUE(source_cursor, 3, birthdate_var); 
 
  -- Bind the row into the cursor that inserts into the destination table. You 
  -- could alter this example to require the use of dynamic SQL by inserting an 
  -- if condition before the bind. 
        DBMS_SQL.BIND_VARIABLE(destination_cursor, ':id_bind', id_var); 
        DBMS_SQL.BIND_VARIABLE(destination_cursor, ':name_bind', name_var); 
        DBMS_SQL.BIND_VARIABLE(destination_cursor, ':birthdate_bind', 
birthdate_var); 
        ignore := DBMS_SQL.EXECUTE(destination_cursor); 
      ELSE 
 
  -- No more rows to copy: 
        EXIT; 
      END IF; 
    END LOOP; 
 
  -- Commit and close all cursors: 
     COMMIT; 
     DBMS_SQL.CLOSE_CURSOR(source_cursor); 
     DBMS_SQL.CLOSE_CURSOR(destination_cursor); 
   EXCEPTION 
     WHEN OTHERS THEN 
       IF DBMS_SQL.IS_OPEN(source_cursor) THEN 
         DBMS_SQL.CLOSE_CURSOR(source_cursor); 
       END IF; 
       IF DBMS_SQL.IS_OPEN(destination_cursor) THEN 
         DBMS_SQL.CLOSE_CURSOR(destination_cursor); 
       END IF; 
       RAISE; 
  END; 
/

解决方案 »

  1.   

    CREATE OR REPLACE TRIGGER manager_info_insert
    INSTEAD OF INSERT ON manager_info
    REFERENCING NEW AS n                 -- new manager informationFOR EACH ROW
    DECLARE
       rowcnt number;
    BEGIN
       SELECT COUNT(*) INTO rowcnt FROM Emp_tab WHERE empno = :n.empno;
       IF rowcnt = 0  THEN
           INSERT INTO Emp_tab (empno,ename) VALUES (:n.empno, :n.ename);
       ELSE
          UPDATE Emp_tab SET Emp_tab.ename = :n.ename
             WHERE Emp_tab.empno = :n.empno;
       END IF;
       SELECT COUNT(*) INTO rowcnt FROM Dept_tab WHERE deptno = :n.deptno;
       IF rowcnt = 0 THEN
          INSERT INTO Dept_tab (deptno, dept_type) 
             VALUES(:n.deptno, :n.dept_type);
       ELSE
          UPDATE Dept_tab SET Dept_tab.dept_type = :n.dept_type
             WHERE Dept_tab.deptno = :n.deptno;
       END IF;
       SELECT COUNT(*) INTO rowcnt FROM Project_tab 
          WHERE Project_tab.projno = :n.projno;
       IF rowcnt = 0 THEN
          INSERT INTO Project_tab (projno, prj_level) 
             VALUES(:n.projno, :n.prj_level);
       ELSE
          UPDATE Project_tab SET Project_tab.prj_level = :n.prj_level
             WHERE Project_tab.projno = :n.projno;
       END IF;
    END;
    /