计算2个光标的结果

问题描述 投票:0回答:1

这是另一个问题的后续内容:使用 REGEXP_LIKE 立即执行中的转义问题

现在我想逐行比较 2 个不同光标的结果。我的循环无法正常工作,并且得到笛卡尔积,因此一个光标的每一行都会逐个连接到另一个光标的所有结果。

SET SERVEROUTPUT ON;

DECLARE
    v_count_rows_diff  NUMBER;
---------VARIABLES--------ORA1--------------------------
    v_1_owner            VARCHAR2(40);
    v_1_table_name       VARCHAR2(40);
    v_1_column_name      VARCHAR2(40);
    v_1_count_rows       NUMBER;
   -- v_1_count_real_rows  NUMBER;
    v_1_rn_tables        NUMBER;
    v_1_count_tables     NUMBER;
    v_1_max_primary_key  VARCHAR2(4000);
    v_1_min_primary_key  VARCHAR2(4000);
    v_1_sum_primary_key  VARCHAR2(4000);
    sql_stmt_1           VARCHAR2(32767);
---------VARIABLES---------ORA2----------------------
    v_2_owner            VARCHAR2(40);
    v_2_table_name       VARCHAR2(40);
    v_2_column_name      VARCHAR2(40);
    v_2_count_rows       NUMBER;
   -- v_2_count_real_rows  NUMBER;
    v_2_rn_tables        NUMBER;
    v_2_count_tables     NUMBER;
    v_2_max_primary_key  VARCHAR2(4000);
    v_2_min_primary_key  VARCHAR2(4000);
    v_2_sum_primary_key  VARCHAR2(4000);
    sql_stmt_2           VARCHAR2(32767);
-------------CURSOR----ORA1--------------------------
    CURSOR get_tables_1 IS
SELECT
        cons.owner,
        cols.table_name,
        cols.column_name as primary_key,
   --        case tab_col.data_type when 'NUMBER' THEN 'numerical' else 'not' end as data_type,
    --    nvl(num_rows, - 1)                  AS count_rows,
        ROW_NUMBER()
        OVER(PARTITION BY cons.owner
             ORDER BY cols.table_name
        )                                   AS rn_tables,
        COUNT(DISTINCT cols.table_name)
        OVER(PARTITION BY cons.owner
        ) AS count_tables
    FROM
        all_constraints   cons,
        all_cons_columns  cols,
        all_tables        tab,
        all_tab_columns   tab_col
    WHERE
            cols.table_name = tab.table_name
        AND cons.constraint_type = 'P'
        AND cons.constraint_name = cols.constraint_name
        AND cons.owner = cols.owner
        AND tab.table_name NOT LIKE '%_MV'
        AND cols.position = 1
        and tab_col.table_name = cols.table_name 
        and cols.column_name = tab_col.column_name
    ORDER BY
        cons.owner,
        cols.table_name,primary_key;
--------------CURSOR----ORA2----------------------
    CURSOR get_tables_2 IS
SELECT
        cons.owner,
        cols.table_name,
        cols.column_name as primary_key,
     --   nvl(num_rows, - 1)                  AS count_rows,
        ROW_NUMBER()
        OVER(PARTITION BY cons.owner
             ORDER BY cols.table_name
        )                                   AS rn_tables,
        COUNT(DISTINCT cols.table_name)
        OVER(PARTITION BY cons.owner
        ) AS count_tables
    FROM
        all_constraints@INST2   cons,
        all_cons_columns@INST2   cols,
        all_tables@INST2         tab,
        all_tab_columns@INST2    tab_col
    WHERE
            cols.table_name = tab.table_name
        AND cons.constraint_type = 'P'
        AND cons.constraint_name = cols.constraint_name
        AND cons.owner = cols.owner
        AND tab.table_name NOT LIKE '%_MV'
        AND cols.position = 1
        and tab_col.table_name = cols.table_name 
        and cols.column_name = tab_col.column_name
    ORDER BY
        cons.owner,
        cols.table_name,primary_key;
BEGIN
---------------SQL---ORA1----------------------
    OPEN get_tables_1;
    LOOP
        FETCH get_tables_1 INTO
            v_1_owner,
            v_1_table_name,
            v_1_column_name,
         --   v_1_count_real_rows,
            v_1_rn_tables,
            v_1_count_tables;
        EXIT WHEN get_tables_1%notfound;
         -- dbms_output.put_line('Tabelle ' || v_1_owner ||' ' || v_1_table_name||' ' || v_1_column_name||' ' || v_1_count_real_rows  ); 

sql_stmt_1 := 'SELECT COUNT(*) as count_rows,'
                || 'max(' || dbms_assert.enquote_name(v_1_column_name, false) || ') as max_primary_key, '
                || 'min(' || dbms_assert.enquote_name(v_1_column_name, false) || ') as min_primary_key, '
                || 'SUM( CASE WHEN REGEXP_LIKE('
                         || dbms_assert.enquote_name(v_1_column_name, false)
                         || ',''^[+-]?\d*\.?\d+$'') '
                         || 'THEN to_number(' || dbms_assert.enquote_name(v_1_column_name, false) || ') '
                         || 'ELSE 0 '
                         || 'END'
                || ') as sum_primary_key FROM '
            || DBMS_ASSERT.ENQUOTE_NAME(v_1_owner, FALSE)
                     || '.'
                     || DBMS_ASSERT.ENQUOTE_NAME(v_1_table_name, FALSE);
        --dbms_output.put_line(sql_stmt_1);
        EXECUTE IMMEDIATE sql_stmt_1
        INTO
            v_1_count_rows,
            v_1_max_primary_key,
            v_1_min_primary_key,
            v_1_sum_primary_key
           ;
----------------SQL--ORA2----------------------
     
             OPEN get_tables_2;
             loop
        FETCH get_tables_2 INTO
            v_2_owner,
            v_2_table_name,
            v_2_column_name,
          --  v_2_count_real_rows,
            v_2_rn_tables,
            v_2_count_tables;
        EXIT WHEN get_tables_2%notfound;
         -- dbms_output.put_line('Tabelle ' || v_2_owner ||' ' || v_2_table_name||' ' || v_2_column_name||' ' || v_2_count_real_rows  ); 
sql_stmt_2 := 'SELECT COUNT(*) as count_rows,'
                || 'max(' || dbms_assert.enquote_name(v_2_column_name, false) || ') as max_primary_key, '
                || 'min(' || dbms_assert.enquote_name(v_2_column_name, false) || ') as min_primary_key, '
                || 'SUM( CASE WHEN REGEXP_LIKE('
                         || dbms_assert.enquote_name(v_2_column_name, false)
                         || ',''^[+-]?\d*\.?\d+$'') '
                         || 'THEN to_number(' || dbms_assert.enquote_name(v_2_column_name, false) || ') '
                         || 'ELSE 0 '
                         || 'END'
                || ') as sum_primary_key FROM '
            || DBMS_ASSERT.ENQUOTE_NAME(v_2_owner, FALSE)
                     || '.'
                     || DBMS_ASSERT.ENQUOTE_NAME(v_2_table_name, FALSE);
        --dbms_output.put_line(sql_stmt_2);
        EXECUTE IMMEDIATE sql_stmt_2
        INTO
            v_2_count_rows,
            v_2_max_primary_key,
            v_2_min_primary_key,
            v_2_sum_primary_key
           ;
           
               v_count_rows_diff := v_1_count_rows - v_2_count_rows;
        IF v_count_rows_diff <> 0 THEN
            dbms_output.put_line(v_1_rn_tables
                                 || ' out of '
                                 || v_1_count_tables
                                 || ' Tabelle: '
                                 || v_1_owner 
                                 || '.'
                                 || v_1_table_name
                                 || ' MaxPimaryKey: '
                                 || v_1_max_primary_key || ' / ' || v_2_max_primary_key
                                 || '; MinPimaryKey: '
                                 || v_1_min_primary_key  || ' / ' || v_2_min_primary_key
                                 || '; SumPimaryKey: '
                                 || v_1_sum_primary_key || ' / ' || v_2_sum_primary_key
                                 || '; Anzahl Datensätze: '
                                 || v_1_count_rows || ' / ' || v_2_count_rows
                                 || '; Differenz: '
                                 || v_count_rows_diff);
        END IF;
         end loop;
    CLOSE get_tables_2;
        END LOOP;
        CLOSE get_tables_1;
END;
oracle plsql
1个回答
0
投票

我得到笛卡尔积,因此一个游标的每一行都会依次连接到另一个游标的所有结果。

在这种情况下,不要使用嵌套循环:

BEGIN
  OPEN get_tables_1;
  LOOP
    -- ...
    OPEN get_tables_2;
    LOOP
      -- ...
    END LOOP;
  END LOOP;
END;
/

前一个循环结束后开始第二个循环:

BEGIN
  OPEN get_tables_1;
  LOOP
    -- ...
  END LOOP;

  OPEN get_tables_2;
  LOOP
    -- ...
  END LOOP;
END;
/
© www.soinside.com 2019 - 2024. All rights reserved.