Dengan asumsi temp1
. Anda dan temp2
tabel memiliki kolom yang sama, mudah dilakukan ketika Anda menggunakan EXECUTE IMMEDIATE
, dan mengetahui cara menelusuri tabel sistem Oracle ALL_TABLES
dan ALL_TAB_COLUMNS
.
Karena saya tidak tahu berapa banyak kolom temp
tabel miliki, idenya adalah untuk membandingkan (dengan MINUS
asli Anda) ide) hasil penggabungan kolom. Hati-hati Anda tidak dapat menggabungkan semuanya dengan cara yang sama (mis. tanggal), jadi saya menunjukkan bagaimana Anda bisa mendapatkan DATA_TYPE
.
Setelah Anda mendapatkan hasil di atas, Anda dapat melihat kolom yang berubah secara manual. Jika saya punya waktu, saya akan menambahkan bagian tentang kolom yang diubah:
- jika Anda memiliki PK, maka kita dapat menggunakannya untuk mengetahui baris yang berubah dan mengulang lagi pada kolom;
- jika tidak ada PK, itu bisa menjadi lebih rumit...
Saya sangat senang melakukan ini, jadi saya akan mencoba membuat kode kecil untuk itu, dengan asumsi PK Anda adalah kolom tunggal yang disebut 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;
/
data uji:
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;
/
Hasil:
2 -> 2aabbcc
COLUMN3:bb<>b
4 not in temp2
Ini terinspirasi oleh Cari Semua Bidang Di Semua Tabel Untuk Nilai Tertentu (Oracle) di mana teknik dasar dijelaskan.