所以问题是这样的:
我有一个包含两列的表,即源查询和目标查询。 每行包含来自源端和目标端的informatica映射的sql查询,我们需要构建一个协调过程,为每行获取这两个值并生成输出并将其存储在临时表中,例如temp1和temp2然后比较这两个临时表的结果。我这样做是通过创建两个表然后通过两个游标进行批量获取,并使用减去集合运算符对两个表进行比较,然后我们从那里得到不同的行。
现在有了棘手的部分,我们要做的是检查那些具有不同值的行,并输出存在更改的列的名称,并输出源端值(temp1)和目标端值( TEMP2)。
如果我之前已经了解了表的结构,那么硬编码是一种实现方法,但由于表temp1
和temp2
正在动态创建,因此我无法让我了解这种情况,我的意思是如何使用一个动态循环遍历行的过程获取列名和这两个值,并检查值的变化位置,然后输出这两个值和列名。
救救我!如果你为我提供了一个代码,那将非常有帮助。
样本数据集
SOURCE
PK COLUMN1 COLUMN2 COLUMN3 COLUMN4
2 NAME2 VALUE2 3 4
1 NAME1 VALUE1 2 3
3 NAME3 VALUE3 4 5
TARGET
PK COLUMN1 COLUMN2 COLUMN3 COLUMN4
1 NAME1 VALUE1 2 3
2 NAME2 VALUE2 4 4
3 NAME3 VALUE3 4 5
现在
SELECT * FROM SOURCE MINUS SELECT * FROM TARGET
给出
PK COLUMN1 COLUMN2 COLUMN3 COLUMN4
2 NAME2 VALUE2 3 4
和
SELECT * FROM TARGET MINUS SELECT * FROM SOURCE
给出
PK COLUMN1 COLUMN2 COLUMN3 COLUMN4
2 NAME2 VALUE2 4 4
我们可以看到column3
值已从3更改为4.
所以我们需要的是这样的东西
COLUMN_NAME OLD_VALUE NEW_VALUE
COLUMN3 3 4
表源和目标是从一个过程创建的,该过程将sql用于源表和目标表用于另一个具有两列的表,一列是源查询,另一列是目标查询,此表中的每一行都有不同的查询查询下次创建这些表时,列数和名称可能会更改。
答案 0 :(得分:1)
假设您的temp1
和temp2
表具有相同的列,使用EXECUTE IMMEDIATE
时很容易做到,并且知道如何浏览Oracle系统表ALL_TABLES
和{ {1}}。
由于我不知道表ALL_TAB_COLUMNS
列有多少列,因此我们的想法是(与原始temp
想法)比较列的串联结果。请注意,您无法以相同的方式连接所有内容(例如日期),因此我展示了如何获得MINUS
。
获得上述结果后,您可以手动查看更改的列。如果我有时间,我会添加有关更改列的部分:
我这样做很有意思,所以我会尝试为它编写一个小代码,假设您的PK是单列DATA_TYPE
:
PK
create or replace procedure compare_tables(t1 in varchar2, t2 in varchar2)
is
v_qry varchar2(10000);
TYPE T_MY_LIST IS TABLE OF VARCHAR2(32000);
v_cols T_MY_LIST; -- list of columns
v_types T_MY_LIST; -- list of columns' type
v_cmp_cols T_MY_LIST; -- list of distinct
v_col_t1_t2 T_MY_LIST; -- t1 minus t2 - value of lines
v_pk_t1_t2 T_MY_LIST; -- associated PKs in t1 minus t2
v_col_t2_t1 T_MY_LIST; -- t2 minus t1 - value of lines
v_pk_t2_t1 T_MY_LIST; -- associated PKs in t2 minus t1
TYPE T_Y_ IS TABLE OF VARCHAR2(32000) index by varchar2(1000);
v_s varchar2(1000); -- for indexing
v_t1_t2 T_Y_; -- list of distinct lines from t1 - t2 /indexed by PK
v_t2_t1 T_Y_; -- list of distinct lines from t2 - t1 /indexed by PK
begin
-- the below assumes all tables have a PK called simply "PK".
v_qry:='PK, ';
execute immediate ' select COLUMN_NAME, DATA_TYPE '
||' from ALL_TAB_COLUMNS where TABLE_NAME=upper('''||t1||''')'
bulk collect into v_cols, v_types;
-- building query with list of columns:
FOR I in 1..v_cols.count loop -- dbms_output.put_line(v_cols(i)||'.'||v_types(i));
v_qry := v_qry||v_cols(i)||'||';
end loop;
v_qry := v_qry||'''''';
execute immediate ' select '||v_qry||' from '||t1||' minus select '||v_qry||' from '||t2
bulk collect into v_pk_t1_t2, v_col_t1_t2;
execute immediate ' select '||v_qry||' from '||t2||' minus select '||v_qry||' from '||t1
bulk collect into v_pk_t2_t1, v_col_t2_t1;
-- build indexed structures that will help compare lines brought by "minus" queries
FOR I in 1..v_pk_t1_t2.count loop
v_t1_t2(v_pk_t1_t2(i)):=v_col_t1_t2(i);
end loop;
FOR I in 1..v_pk_t2_t1.count loop
v_t2_t1(v_pk_t2_t1(i)):=v_col_t2_t1(i);
end loop;
v_s := v_t1_t2.FIRST; -- Get first element of array
WHILE v_s IS NOT NULL LOOP
if (v_t2_t1.exists(v_s)) then
-- distinct rows on same PK
DBMS_Output.PUT_LINE (v_s || ' -> ' || v_t1_t2(v_s));
-- loop on each column joined on PK:
FOR i in 1..v_cols.count
loop
v_qry:= 'select '''||v_cols(i)||':''||'||t1||'.'||v_cols(i)||'||''<>''||'||t2||'.'||v_cols(i)
||' from '||t1||','||t2
||' where '||t1||'.PK='||t2||'.PK'
||' and '||t1||'.PK='||v_s
||' and '||t1||'.'||v_cols(i)||'<>'||t2||'.'||v_cols(i)
;
--DBMS_Output.PUT_LINE (v_qry);
execute immediate v_qry bulk collect into v_cmp_cols;
FOR j in 1..v_cmp_cols.count loop
DBMS_Output.PUT_LINE (v_cmp_cols(j));
end loop;
end loop;
else
DBMS_Output.PUT_LINE (v_s || ' not in ' || t2);
end if;
v_s := v_t1_t2.NEXT(v_s); -- Get next element of array
END LOOP;
v_s := v_t2_t1.FIRST; -- Get first
WHILE v_s IS NOT NULL LOOP
if (not v_t1_t2.exists(v_s)) then
DBMS_Output.PUT_LINE (v_s || ' not in ' || t1);
end if;
v_s := v_t2_t1.NEXT(v_s); -- Get next
END LOOP;
end compare_tables;
/
create table temp1 (PK number,
COLUMN1 varchar2(10),
COLUMN2 varchar2(10),
COLUMN3 varchar2(10),
COLUMN4 varchar2(10)
);
create table temp2 (PK number,
COLUMN1 varchar2(10),
COLUMN2 varchar2(10),
COLUMN3 varchar2(10),
COLUMN4 varchar2(10)
);
delete temp1;
insert into temp1
select 1, 'a', 'a', 'bb', 'cc' from dual
union all select 2, 'a', 'a', 'bb', 'cc' from dual
union all select 3, 'a', 'a', 'bb', 'cc' from dual
union all select 4, 'a', 'a', 'bb', 'cc' from dual
;
insert into temp2
select 1, 'a', 'a', 'bb', 'cc' from dual
union all select 2, 'a', 'a', 'b', 'cc' from dual
union all select 3, 'a', 'a', 'bb', 'cc' from dual
;
begin
compare_tables('temp1','temp2');
end;
/
这受到Search All Fields In All Tables For A Specific Value (Oracle)的启发,其中解释了基本的技术。