我获得了一个存储过程,它生成一个打开的游标,作为输出传递给报告工具。我重写了这个存储过程以提高性能。我想要做的是显示给定的一组输入参数的两个结果集是相同的。
相当于:
的东西select * from CURSOR_NEW
minus
select * from CURSOR_OLD
union all
select * from CURSOR_OLD
minus
select * from CURSOR_NEW
每个游标从一大部分表中返回几十列。每行都有一个id值,以及该id的其他列值的长列表。我想查一下:
如果它只是一列或两列,我可以连接它们并找到一个哈希值,然后在光标上加总。或者另一种方法可能是创建一个父程序,将光标结果插入到全局临时表中并比较结果。但是,由于它是几十个专栏,我试图找到一种不那么强力的方法来进行比较。
如果解决方案可以针对涉及不同游标的其他情况进行扩展,那么这将是很好的,因此不必每次都手动重写,因为这是我经常遇到的情况。
答案 0 :(得分:1)
我找到了一种方法来做到这一点。这比我想象的要复杂得多。我最终使用了一些DBMS_SQL过程,允许将REFCURSOR转换为定义的游标。 Oracle在此处提供了相关文档: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/dynamic.htm#LNPLS00001
之后,我将行值连接成一个字符串并打印出哈希值。对于更大的游标,我将更改concat_col_vals以使用CLOB来防止它溢出。
p_testCursors返回一个简单的refcursor,用于示例目的。
declare
cx_1 sys_refcursor;
c NUMBER;
desctab DBMS_SQL.DESC_TAB;
colcnt NUMBER;
stringvar VARCHAR2(4000);
numvar NUMBER;
datevar DATE;
concat_col_vals varchar2(4000);
col_hash number;
h raw(32767);
n number;
BEGIN
p_testCursors(cx_1);
c := DBMS_SQL.TO_CURSOR_NUMBER(cx_1);
DBMS_SQL.DESCRIBE_COLUMNS(c, colcnt, desctab);
-- Define columns:
FOR i IN 1 .. colcnt LOOP
IF desctab(i).col_type = 2 THEN
DBMS_SQL.DEFINE_COLUMN(c, i, numvar);
ELSIF desctab(i).col_type = 12 THEN
DBMS_SQL.DEFINE_COLUMN(c, i, datevar);
-- statements
ELSE
DBMS_SQL.DEFINE_COLUMN(c, i, stringvar, 4000);
END IF;
END LOOP;
-- Fetch rows with DBMS_SQL package:
WHILE DBMS_SQL.FETCH_ROWS(c) > 0 LOOP
concat_col_vals := '~';
FOR i IN 1 .. colcnt LOOP
IF (desctab(i).col_type = 1) THEN
DBMS_SQL.COLUMN_VALUE(c, i, stringvar);
--Dbms_Output.Put_Line(stringvar);
concat_col_vals := concat_col_vals || '~' || stringvar;
ELSIF (desctab(i).col_type = 2) THEN
DBMS_SQL.COLUMN_VALUE(c, i, numvar);
--Dbms_Output.Put_Line(numvar);
concat_col_vals := concat_col_vals || '~' || to_char(numvar);
ELSIF (desctab(i).col_type = 12) THEN
DBMS_SQL.COLUMN_VALUE(c, i, datevar);
--Dbms_Output.Put_Line(datevar);
concat_col_vals := concat_col_vals || '~' || to_char(datevar);
-- statements
END IF;
END LOOP;
DBMS_OUTPUT.PUT_LINE(concat_col_vals);
col_hash := DBMS_UTILITY.GET_SQL_HASH(concat_col_vals, h, n);
DBMS_OUTPUT.PUT_LINE('Return Value: ' || TO_CHAR(col_hash));
DBMS_OUTPUT.PUT_LINE('Hash: ' || h);
END LOOP;
DBMS_SQL.CLOSE_CURSOR(c);
END;
/
答案 1 :(得分:0)
这对Oracle来说不是一件容易的事。
你可以在dba-oracle web上找到 非常好的文章:
Sql patterns symmetric diff
和Convert set to join sql parameter
如果您经常需要,您可以:
你可以在文章中找到其他可能性。