使用游标更新嵌套表pl / sql

时间:2018-11-10 21:59:14

标签: oracle plsql

我正在嵌套表格

create or replace type comm_type as object
 (comm_month varchar(5),
 comm_amount  number); 

create or replace TYPE comm_array AS VARRAY(12) OF comm_type;

alter table emp2 add commission comm_array

现在的问题是如何使用光标更新comm_amount列?

现在,有了这个,但是我无法访问子表(委托,有什么建议吗?

DECLARE 
  CURSOR c_comm_amount_cursor IS 
   select c.comm_amount
    from emp2 e, table (e.commission) c
    where c.comm_month = 'DEC' for update of c.comm_month nowait;
BEGIN
   FOR emp_record IN c_comm_amount_cursor LOOP
    UPDATE emp2
     SET  emp2.commission.comm_amount = emp2.commission.comm_amount + 100
     WHERE CURRENT OF c_emp_cursor;
  END LOOP;
END;
/

编辑

这是我的桌子的桌子:

Name       Null?    Type         
---------- -------- ------------ 
EMPNO      NOT NULL NUMBER(4)    
ENAME               VARCHAR2(10)    
BONUS               NUMBER       
COMMISSION          COMM_ARRAY

comm_array->12*times(comm_month, comm_amount)

我要在特定月份更新comm_amount。

解决方案

DECLARE 
  CURSOR c_comm_amount_cursor IS 
   select c.comm_amount,c.comm_month, e.empno
    from emp2 e, table (e.commission) c
    where c.comm_month = 'DEC'for update of c.comm_month nowait;

BEGIN
  FOR emp_record IN c_comm_amount_cursor 
  LOOP
     UPDATE table(Select commission from emp2 where empno = emp_record.empno) e 
     SET  e.comm_amount = e.comm_amount + 100
     WHERE CURRENT OF c_comm_amount_cursor;
 END LOOP;
END;
/

2 个答案:

答案 0 :(得分:1)

使用varrays时几乎没有限制。其中之一是,当您对具有数据类型为DML的列的表执行varray操作时,如示例所示。您可以使用Nested table并达到您的要求,如下面的演示所示。但是,请记住,嵌套表操作非常复杂。请参阅下文并阅读内联注释。

--Created Table emp2 with an additional column
CREATE TABLE emp2 (ename VARCHAR2(10));

--Object 
CREATE OR REPLACE TYPE COMM_TYPE AS OBJECT
 (COMM_MONTH VARCHAR(5),
 COMM_AMOUNT  NUMBER); 

--Created a Table of object rather then varray.
CREATE OR REPLACE  TYPE COMM_ARRAY AS TABLE OF COMM_TYPE;

--Modified table emp2. Added column commission as shown in your example
ALTER  TABLE EMP2 ADD COMMISSION COMM_ARRAY NESTED TABLE COMMISSION STORE AS TBA1;

--Inserted records
INSERT INTO EMP2 VALUES('AAA',COMM_ARRAY(COMM_TYPE('NOV',100)));
INSERT INTO EMP2 VALUES('BBB',COMM_ARRAY(COMM_TYPE('DEC',200)));

--Selected Records
SQL> SELECT C.COMM_AMOUNT,C.COMM_MONTH
  2      FROM EMP2 E, TABLE (E.COMMISSION) C
  3      WHERE C.COMM_MONTH = 'DEC';

COMM_AMOUNT COMM_
----------- -----
        200 DEC   

-阻止更新记录

DECLARE 
  CURSOR c_comm_amount_cursor IS 
   select c.comm_amount,c.comm_month
    from emp2 e, table (e.commission) c
    where c.comm_month = 'DEC'for update of c.comm_month nowait;
BEGIN
  FOR emp_record IN c_comm_amount_cursor 
  LOOP
     --With the help of table operator you can update records of a nested table but not varray.
     UPDATE table( Select commission from emp2 where ename = 'BBB') e --<--Make sure to use additional column of the table to make unique record selection for update
     SET  e.comm_amount = e.comm_amount + 100    
     WHERE CURRENT OF c_comm_amount_cursor;
 END LOOP;
 COMMIT;
END;
/

-您可以看到更新已完成。

SQL> /

COMM_AMOUNT COMM_
----------- -----
        300 DEC

此外,如注释中所述,循环的使用看起来是多余的,并且可以进一步简化该块,如下所示:

BEGIN
     --With the help of table operator you can update records of a nested table but not varray.
 UPDATE table( Select commission from emp2 where ename = 'BBB') e --<--Make sure to use additional column of the table to make unique record selection for update
   SET  e.comm_amount = e.comm_amount + 100    
   WHERE  e.comm_month ='DEC';

 COMMIT;
END;

编辑:

  

我该如何更新每位员工,在这里您只选择一位带姓名的员工   'BBB'。有办法吗?

如我的评论中所述,您可以使用dynamic SQL更新所有员工,如下所示:

DECLARE 
v_sql varchar2(2000);
CURSOR c_enme_cursor IS 
   select ename
    from emp2;
BEGIN
FOR emp_recd IN c_enme_cursor 
LOOP
 v_sql:=q'[
           UPDATE table( Select commission from emp2 where ename = ']'||emp_recd.ename||q'[') e 
             SET  e.comm_amount = e.comm_amount + 100    
            -- WHERE  e.comm_month ='DEC'
          ]';
  EXECUTE IMMEDIATE V_SQL;          
END LOOP;
COMMIT;
END;

答案 1 :(得分:0)

您好,最快的答案是:

DECLARE
   CURSOR C_COMM_AMOUNT_CURSOR
   IS
      SELECT ROWID ROW_ID
      FROM EMP2 E
      WHERE E.COMM_MONTH = 'DEC';
BEGIN
   FOR EMP_RECORD IN C_COMM_AMOUNT_CURSOR
   LOOP
      UPDATE TABLE (
                    SELECT COMMISSION
                    FROM EMP2
                    WHERE ROWID = ROW_ID
                   )
      SET COMM_AMOUNT = COMM_AMOUNT + 100
      WHERE ;--your where clause condition
   END LOOP;
END;

您应该知道在使用嵌套表时,必须在SQL脚本中的嵌套表周围使用 TABLE(),在PL / SQL中,它有点复杂,您必须创建一个嵌套对象运行时,并用您的数据填充它并进行操作,然后将其保存到您的表中,这太离谱了,我遇到了这个问题,并且使用 ROWID 更具可读性。