从数组插入数据时,如何解决Oracle Subscript计数错误?

时间:2018-07-18 09:31:32

标签: oracle stored-procedures plsql oracle12c

我已经开发了这样的存储过程:

        create or replace 
        PROCEDURE PROC_INS (
              GB_LD_ID   IN NUMBER,
              GB_CS_SP       IN TBL_CHAR,
              GB_UF_NMS    IN TBL_CHAR,
              GB_RW_BRS   IN TBL_NBR,
              GB_RT_SMS       IN TBL_CHAR,
              GB_LC_SD     IN TBL_CHAR)
        AS

          LV_ERROR   NUMBER(10);
          LV_MESSAGE varchar2(512);
          LV_TM_DI NUMBER(19);

        BEGIN


        select max(ID) into LV_TM_DI from TME_TAB;
        if(LV_TM_DI  IS NULL)THEN
           LV_TM_DI:=0;
        end if;

          FOR i IN GB_RW_BRS.FIRST..GB_RW_BRS.LAST
          LOOP
            BEGIN
              Insert into TME_TAB (ID,VS,PUCS,DT_CRD,NGL_ID,NAME,UD_DT,RW_NHG,TRF_SM,LS_FD)
              Values((LV_TM_DI+1),0,GB_CS_SP(i),SYSTIMESTAMP,GB_LD_ID,GB_UF_NMS(i),SYSTIMESTAMP,GB_RW_BRS(i),GB_RT_SMS(i),GB_LC_SD(i));
            END;
            LV_TM_DI := LV_TM_DI + 1;
          END LOOP;
          COMMIT;


        EXCEPTION
        WHEN OTHERS THEN
           IF(LV_MESSAGE IS NULL) THEN
            LV_ERROR    :=-20004;
            LV_MESSAGE  :=SQLERRM;
          END IF;
          RAISE_APPLICATION_ERROR (LV_ERROR,LV_MESSAGE);

        END PROC_INS;

此过程通过读取类型为TBL_CHARTBL_NBR的数组来插入记录。 TBL_CHAR的定义如下:

create or replace TYPE "TBL_CHAR" AS TABLE OF VARCHAR2(100);

但是在插入过程中,我得到以下错误:ORA-20004: ORA-06533: Subscript beyond count

有人可以帮我吗?

2 个答案:

答案 0 :(得分:0)

类似数组的元素数量不同。我的测试:

create or replace type tbl_char as table of varchar2(100);
create or replace type tbl_nbr as table of number;
create table tme_tab(id number(3), nbr number(5), chr varchar2(100));

create or replace procedure proc_ins ( i_id in number, i_nbr in tbl_nbr, i_chr in tbl_char ) as
    lv_tm_di number(6);
begin
    select nvl(max(ID), 0) into lv_tm_di from tme_tab;

    for i in i_nbr.first..i_nbr.last loop
        lv_tm_di := lv_tm_di + 1;
        begin
            insert into tme_tab (id, nbr, chr) values(lv_tm_di, i_nbr(i), i_chr(i));
        end;
    end loop;
end proc_ins;

...这可行:

begin 
    proc_ins(1, tbl_nbr(1, 7, 0), tbl_char('P', 'Q', 'R'));
end;

...,这不起作用(ORA-06533):

begin 
    proc_ins(1, tbl_nbr(1, 7, 0, 9), tbl_char('P', 'Q', 'R'));
end;

在插入之前检查大小并引发异常:

    if i_nbr.count <> i_chr.count then
        raise_application_error (-20001, 'wrong array dimmensions');
    end if;

或为更短的数组插入null。另外,您的过程在生成ID时会使用计数器,请考虑改为使用顺序,这对于并发更新很重要。

答案 1 :(得分:0)

  • 使用SEQUENCE获取唯一ID(而不是MAX)。
  • Don't COMMIT in the procedure,从调用块执行此操作,因为它使您可以在事务中执行多个DML操作,然后在出现问题时将它们全部回滚。
  • 在集合中找到LEAST个条目,并且只插入那么多行。

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE TME_TAB (
  ID int,
  VS int,
  PUCS char(100),
  DT_CRD timestamp,
  NGL_ID number,
  NAME char(100),
  UD_DT timestamp,
  RW_NHG number,
  TRF_SM char(100),
  LS_FD char(100)
)
/

CREATE TYPE TBL_CHAR IS TABLE OF CHAR(100)
/
CREATE TYPE TBL_NBR IS TABLE OF NUMBER
/

CREATE SEQUENCE TME_TAB__ID__SEQ
/

create or replace PROCEDURE PROC_INS (
  GB_LD_ID  IN NUMBER,
  GB_CS_SP  IN TBL_CHAR,
  GB_UF_NMS IN TBL_CHAR,
  GB_RW_BRS IN TBL_NBR,
  GB_RT_SMS IN TBL_CHAR,
  GB_LC_SD  IN TBL_CHAR)
AS
  LV_ERROR   NUMBER(10);
  LV_MESSAGE varchar2(512);
  LV_TM_DI NUMBER(19);
BEGIN
  FOR i IN 1 .. LEAST(
                  GB_CS_SP.COUNT,
                  GB_UF_NMS.COUNT,
                  GB_RW_BRS.COUNT,
                  GB_RT_SMS.COUNT,
                  GB_LC_SD.COUNT
                )
  LOOP
    Insert into TME_TAB (
      ID,            VS,           PUCS,         DT_CRD,
      NGL_ID,        NAME,         UD_DT,        RW_NHG,
      TRF_SM,        LS_FD
    ) Values(
      TME_TAB__ID__SEQ.NEXTVAL,  0, GB_CS_SP(i),  SYSTIMESTAMP,
      GB_LD_ID,      GB_UF_NMS(i), SYSTIMESTAMP, GB_RW_BRS(i),
      GB_RT_SMS(i),  GB_LC_SD(i)
    );
  END LOOP;
EXCEPTION
  WHEN OTHERS THEN
    IF(LV_MESSAGE IS NULL) THEN
      LV_ERROR    :=-20004;
      LV_MESSAGE  :=SQLERRM;
    END IF;
    RAISE_APPLICATION_ERROR (LV_ERROR,LV_MESSAGE);
END PROC_INS;
/

查询1

BEGIN
  PROC_INS (
    GB_LD_ID  => 1,
    GB_CS_SP  => TBL_CHAR( 'sp_a', 'sp_b' ),
    GB_UF_NMS => TBL_CHAR( 'nms_a', 'nms_b' ),
    GB_RW_BRS => TBL_NBR( 1.1, 1.2 ),
    GB_RT_SMS => TBL_CHAR( 'sms_a', 'sms_b' ),
    GB_LC_SD  => TBL_CHAR( 'sd_a', 'sd_b' )
  );
  COMMIT;
END;

Results

查询2

SELECT * FROM TME_TAB

Results

| ID | VS |                                                                                                 PUCS |                     DT_CRD | NGL_ID |                                                                                                 NAME |                      UD_DT | RW_NHG |                                                                                               TRF_SM |                                                                                                LS_FD |
|----|----|------------------------------------------------------------------------------------------------------|----------------------------|--------|------------------------------------------------------------------------------------------------------|----------------------------|--------|------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|
|  1 |  0 | sp_a                                                                                                 | 2018-07-18 11:07:31.827742 |      1 | nms_a                                                                                                | 2018-07-18 11:07:31.827742 |    1.1 | sms_a                                                                                                | sd_a                                                                                                 |
|  2 |  0 | sp_b                                                                                                 | 2018-07-18 11:07:31.828545 |      1 | nms_b                                                                                                | 2018-07-18 11:07:31.828545 |    1.2 | sms_b                                                                                                | sd_b                                                                                                 |