这是另一个问题的后续内容:使用 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;
我得到笛卡尔积,因此一个游标的每一行都会依次连接到另一个游标的所有结果。
在这种情况下,不要使用嵌套循环:
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;
/