【问题标题】:PL/sql stored procedure ref cursor as parameterPL/sql 存储过程引用游标作为参数
【发布时间】:2012-04-09 23:03:00
【问题描述】:

我需要将多行传递给存储过程。我可以使用参考光标吗?因为我尝试了以下方法:

我的包裹里面有:

TYPE FACT_VND_RECORD
IS
  RECORD
  (
    COD_NOMCPDT P6PCM2_PARMCMS.COD_NOMCPDT%TYPE,
    LIB_LIBNOMCPDT P6PCM2_PARMCMS.LIB_LIBNOMCPDT%TYPE,
    DHS_MAJ P6PCM2_PARMCMS.DHS_MAJ%TYPE,
    LIB_AUTH_MAJ P6PCM2_PARMCMS.LIB_AUTH_MAJ%TYPE );

TYPE FACT_VND_CURSOR
    IS
      REF
      CURSOR
        RETURN FACT_VND_RECORD;

和2个程序:

PROCEDURE REC_FACT_VND(
      P_IN_NUM_VND   IN OUT P6PCM2_PARMCMS.NUM_VND%TYPE,
      P_OUT_FACT_VND IN OUT FACT_VND_CURSOR,
      P_OUT_CODE_RET OUT INTEGER,
      P_OUT_MSG_ERR OUT VARCHAR2);

  PROCEDURE MAJ_FACT_VND(
      P_IN_NUM_VND   IN OUT P6PCM2_PARMCMS.NUM_VND%TYPE,
      P_IN_FACT_VND IN OUT FACT_VND_CURSOR,
      P_OUT_CODE_RET OUT INTEGER,
      P_OUT_MSG_ERR OUT VARCHAR2); 

接收先前填充的光标并对数据进行处理。

我使用这两个电话;第一个工作正常,我可以看到 ref cursor C1 中的数据,然后我尝试使用它。

C1 PACK_REC_FACT_VND.FACT_VND_CURSOR;
--other definitons
      PACK_REC_FACT_VND.REC_FACT_VND(NUM_VND,C1,COD_RET,MSG_ERR);
    PACK_REC_FACT_VND.MAJ_FACT_VND(NUM_VND,C1,COD_RET,MSG_ERR);

我无法遍历数据,因为它是未定义的: (第二个过程的代码)

LIGNE_TAUX PACK_REC_FACT_VND.FACT_VND_RECORD;
    BEGIN
      DELETE FROM P6PCM2_PARMCMS WHERE NUM_VND=P_IN_NUM_VND;
      FOR LIGNE_TAUX IN P_IN_FACT_VND
      LOOP
        INSERT
        INTO P6PCM2_PARMCMS VALUES
          (
            P_IN_NUM_VND,   
LIGNE_TAUX.COD_NOMCPDT, 
LIGNE_TAUX.LIB_LIBNOMCPDT, 
LIGNE_TAUX.DHS_MAJ, 
LIGNE_TAUX.LIB_AUTH_MAJ);
      END LOOP;

Error(48,21): PLS-00221: 'P_IN_FACT_VND' is not a procedure or is undefined

或者我应该切换到记录表?

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    我们不能像那样使用引用游标;我们需要使用显式游标语法。试试这个(警告:未经测试的代码!):

            LIGNE_TAUX PACK_REC_FACT_VND.FACT_VND_RECORD;
        BEGIN
          DELETE FROM P6PCM2_PARMCMS WHERE NUM_VND=P_IN_NUM_VND;
    
          LOOP
             fetch P_IN_FACT_VND   into LIGNE_TAUX; 
             exit when P_IN_FACT_VND%notfound;
            INSERT
            INTO P6PCM2_PARMCMS VALUES
              (
                P_IN_NUM_VND,   
                LIGNE_TAUX.COD_NOMCPDT, 
                LIGNE_TAUX.LIB_LIBNOMCPDT, 
                LIGNE_TAUX.DHS_MAJ, 
                LIGNE_TAUX.LIB_AUTH_MAJ);
          END LOOP;
    
      close P_IN_FACT_VND;
    

    但是,如果您将记录提取到集合中,则会获得更好的性能。像这样的:

            type LIGNE_TAUX_NT is table of PACK_REC_FACT_VND.FACT_VND_RECORD;
            LIGNE_TAUX_COLL LIGNE_TAUX_NT;
        BEGIN
          DELETE FROM P6PCM2_PARMCMS WHERE NUM_VND=P_IN_NUM_VND;
    
          fetch P_IN_FACT_VND bulk collect  into LIGNE_TAUX_COLL; 
          close P_IN_FACT_VND;
    
          -- while we're at it why not use the more efficient FORALL syntax 
          -- to perform the inserts?
    
    
          forall idx in LIGNE_TAUX_COLL.first() .. LIGNE_TAUX_COLL.last()
                INSERT
               INTO P6PCM2_PARMCMS VALUES
                  (
                P_IN_NUM_VND,   
                LIGNE_TAUX_COLL(idx).COD_NOMCPDT, 
                LIGNE_TAUX_COLL(idx).LIB_LIBNOMCPDT, 
                LIGNE_TAUX_COLL(idx).DHS_MAJ, 
                LIGNE_TAUX_COLL(idx).LIB_AUTH_MAJ);
    

    Find out more

    【讨论】:

    • 记录表是我的第二个想法..我会试一试!并给出答案。
    • 我切换到记录表作为输入参数,因为我觉得使用起来更安全:) 10x 反正
    猜你喜欢
    • 2011-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多