【问题标题】:Handle null values in BULK COLLECT处理 BULK COLLECT 中的空值
【发布时间】:2018-09-30 00:17:24
【问题描述】:

我试图将数据从表 A 传递到表 B,但首先我需要检查我尝试插入的数据是否不在表 B 中。我通过查询如果存在将返回标识来执行此操作。问题是第二次执行引发了唯一的约束冲突,因此看起来要比较表 B 中是否存在的验证不起作用,或者 if 语句中的条件错误。

  DECLARE

       LN_EXIST       NUMBER;

       CURSOR cur
       IS
            SELECT *
              FROM table_A


       TYPE cur_aat IS TABLE OF cur%ROWTYPE
          INDEX BY PLS_INTEGER;

       cur_rows                cur_aat;
    BEGIN
       OPEN cur;

       LOOP
          FETCH cur BULK COLLECT INTO cur_rows LIMIT 1000;

          EXIT WHEN cur%NOTFOUND;                      /* cause of missing rows */

          FOR I IN 1 .. cur_rows.COUNT
          LOOP
             LN_EXIST := 0;

             BEGIN
                DBMS_OUTPUT.put_line (cur_rows (I).PEU_IDENTIFICACION);

                SELECT PUV.PEU_IDENTIFICACION -- check
                         INTO LN_EXIST
                  FROM table_b PUV
                 WHERE (CASE
                           WHEN     PUV.PEU_IDENTIFICACION =
                                       cur_rows (I).PEU_IDENTIFICACION
                                AND NVL (PUV.PEU_PRIMER_NOMBRE, '0') =
                                       NVL (cur_rows (I).PEU_PRIMER_NOMBRE, '0')
                                AND NVL (PUV.PEU_SEGUNDO_NOMBRE, '0') =
                                       NVL (cur_rows (I).PEU_SEGUNDO_NOMBRE, '0')
                                AND PUV.PEU_PRIMER_APELLIDO =
                                       cur_rows (I).PEU_PRIMER_APELLIDO
                                AND NVL (PUV.PEU_SEGUNDO_APELLIDO, '0') =
                                       NVL (cur_rows (I).PEU_SEGUNDO_APELLIDO,
                                            '0')
                                AND PUV.PEU_FECHA_NACIMIENTO =
                                       cur_rows (I).PEU_FECHA_NACIMIENTO
                           THEN
                              'S'
                           ELSE
                              'N'
                        END) = 'S';
             EXCEPTION
                WHEN OTHERS
                THEN
                   LN_EXIST:= 0;
             END;

             IF LN_EXIST!= 0     --if not exist
             THEN
                INSERT
                  INTO table_b (PEU_ID,
                                               PEU_IDENTIFICACION,
                                               PEU_PRIMER_APELLIDO,
                                               PEU_SEGUNDO_APELLIDO,
                                               PEU_PRIMER_NOMBRE,
                                               PEU_SEGUNDO_NOMBRE,
                                               )
                VALUES (cur_rows (I).PEU_ID,     
                        cur_rows (I).PEU_TIPO_IDENTIFICACION,
                        cur_rows (I).PEU_IDENTIFICACION,
                        cur_rows (I).PEU_PRIMER_APELLIDO,
                        cur_rows (I).PEU_SEGUNDO_APELLIDO,
                        cur_rows (I).PEU_PRIMER_NOMBRE,
                        cur_rows (I).PEU_SEGUNDO_NOMBRE,
                        );
             END IF;
          END LOOP;

          EXIT WHEN cur%NOTFOUND;
       END LOOP;

       COMMIT;

       CLOSE cur;
    END;

【问题讨论】:

    标签: oracle plsql plsqldeveloper


    【解决方案1】:

    首先,上面显示的代码不会执行,因为读取的行中有语法错误

    PEU_SEGUNDO_NOMBRE,
    

    cur_rows (I).PEU_SEGUNDO_NOMBRE,
    

    结尾的逗号会导致编译失败。

    其次,逐行处理往往很慢,即使您将数据从数据库批量收集到内存中也是如此。我建议你使用MERGE,它用一条语句替换你的游标和循环逻辑:

    MERGE INTO TABLE_B b
      USING TABLE_A a
        ON (b.PEU_IDENTIFICACION = a.PEU_IDENTIFICACION AND
            NVL(b.PEU_PRIMER_NOMBRE, '0') = NVL (a.PEU_PRIMER_NOMBRE, '0') AND
            NVL (b.PEU_SEGUNDO_NOMBRE, '0') = NVL(a.PEU_SEGUNDO_NOMBRE, '0') AND
            b.PEU_PRIMER_APELLIDO = a.PEU_PRIMER_APELLIDO AND
            NVL(b.PEU_SEGUNDO_APELLIDO, '0') = NVL(a.PEU_SEGUNDO_APELLIDO, '0') AND
            b.PEU_FECHA_NACIMIENTO = a.PEU_FECHA_NACIMIENTO)
      WHEN NOT MATCHED THEN
        INSERT (PEU_ID,
                PEU_IDENTIFICACION,
                PEU_PRIMER_APELLIDO,
                PEU_SEGUNDO_APELLIDO,
                PEU_PRIMER_NOMBRE,
                PEU_SEGUNDO_NOMBRE)
        VALUES (a.PEU_ID,     
                a.PEU_TIPO_IDENTIFICACION,
                a.PEU_IDENTIFICACION,
                a.PEU_PRIMER_APELLIDO,
                a.PEU_SEGUNDO_APELLIDO,
                a.PEU_PRIMER_NOMBRE,
                a.PEU_SEGUNDO_NOMBRE);
    

    祝你好运。

    【讨论】:

    • 如果根本问题是“if 语句中的条件错误”,那么使用 MERGE 语法显然无济于事。但是这个解决方案的代码少得多,这使得在实现的逻辑中很容易发现灯笼裤。
    【解决方案2】:

    我检查了,而不是仅使用 select 语句,我添加了 count 语句,以确定与我设置的参数存在的巧合总数,因此如果不存在,所有时间都将返回一个值 0 和如果存在非 0 的值。

    DECLARE
    
           LN_EXIST       NUMBER;
    
           CURSOR cur
           IS
                SELECT *
                  FROM table_A
    
    
           TYPE cur_aat IS TABLE OF cur%ROWTYPE
              INDEX BY PLS_INTEGER;
    
           cur_rows                cur_aat;
        BEGIN
           OPEN cur;
    
           LOOP
              FETCH cur BULK COLLECT INTO cur_rows LIMIT 1000;
    
              EXIT WHEN cur%NOTFOUND;                      /* cause of missing rows */
    
              FOR I IN 1 .. cur_rows.COUNT
              LOOP
    
                    DBMS_OUTPUT.put_line (cur_rows (I).PEU_IDENTIFICACION);
    
                    SELECT COUNT (PUV.PEU_IDENTIFICACION) -- check
                             INTO LN_EXIST
                      FROM table_b PUV
                     WHERE (CASE
                               WHEN     PUV.PEU_IDENTIFICACION =
                                           cur_rows (I).PEU_IDENTIFICACION
                                    AND NVL (PUV.PEU_PRIMER_NOMBRE, '0') =
                                           NVL (cur_rows (I).PEU_PRIMER_NOMBRE, '0')
                                    AND NVL (PUV.PEU_SEGUNDO_NOMBRE, '0') =
                                           NVL (cur_rows (I).PEU_SEGUNDO_NOMBRE, '0')
                                    AND PUV.PEU_PRIMER_APELLIDO =
                                           cur_rows (I).PEU_PRIMER_APELLIDO
                                    AND NVL (PUV.PEU_SEGUNDO_APELLIDO, '0') =
                                           NVL (cur_rows (I).PEU_SEGUNDO_APELLIDO,
                                                '0')
                                    AND PUV.PEU_FECHA_NACIMIENTO =
                                           cur_rows (I).PEU_FECHA_NACIMIENTO
                               THEN
                                  'S'
                               ELSE
                                  'N'
                            END) = 'S';
    
                 IF LN_EXIST!= 0     --if not exist
                 THEN
                    INSERT
                      INTO table_b (PEU_ID,
                                                   PEU_IDENTIFICACION,
                                                   PEU_PRIMER_APELLIDO,
                                                   PEU_SEGUNDO_APELLIDO,
                                                   PEU_PRIMER_NOMBRE,
                                                   PEU_SEGUNDO_NOMBRE,
                                                   )
                    VALUES (cur_rows (I).PEU_ID,     
                            cur_rows (I).PEU_TIPO_IDENTIFICACION,
                            cur_rows (I).PEU_IDENTIFICACION,
                            cur_rows (I).PEU_PRIMER_APELLIDO,
                            cur_rows (I).PEU_SEGUNDO_APELLIDO,
                            cur_rows (I).PEU_PRIMER_NOMBRE,
                            cur_rows (I).PEU_SEGUNDO_NOMBRE,
                            );
                 END IF;
              END LOOP;
    
              EXIT WHEN cur%NOTFOUND;
           END LOOP;
    
           COMMIT;
    
           CLOSE cur;
        END;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-10
      • 1970-01-01
      • 2018-01-27
      • 1970-01-01
      相关资源
      最近更新 更多