Ich habe zwei ähnliche Tabellen in Oracle in zwei verschiedenen Datenbanken. Zum Beispiel: Mein Tabellenname ist EMPLOYEE und der Primärschlüssel ist die Mitarbeiter-ID. Dieselbe Tabelle mit den gleichen Spalten (50 Spalten sind in zwei Datenbanken avlbl und zwei Datenbanken sind miteinander verbunden.
Ich möchte diese beiden Tabellen spaltenweise vergleichen und herausfinden, welche Datensätze nicht übereinstimmen. Ich möchte die spezifische Spalte in jeder Zeile in zwei Tabellen, die nicht übereinstimmen.
select *
from
(
( select * from TableInSchema1
minus
select * from TableInSchema2)
union all
( select * from TableInSchema2
minus
select * from TableInSchema1)
)
sollte den Trick tun, wenn Sie dies mit einer Abfrage lösen möchten
Als Alternative, die das vollständige Scannen jeder Tabelle erspart und Sie auf einfache Weise feststellen können, welche Tabelle mehr Zeilen mit einer Kombination von Werten als die andere hatte:
SELECT col1
, col2
-- (include all columns that you want to compare)
, COUNT(src1) CNT1
, COUNT(src2) CNT2
FROM (SELECT a.col1
, a.col2
-- (include all columns that you want to compare)
, 1 src1
, TO_NUMBER(NULL) src2
FROM tab_a a
UNION ALL
SELECT b.col1
, b.col2
-- (include all columns that you want to compare)
, TO_NUMBER(NULL) src1
, 2 src2
FROM tab_b b
)
GROUP BY col1
, col2
HAVING COUNT(src1) <> COUNT(src2) -- only show the combinations that don't match
Kredit geht hier: http://asktom.Oracle.com/pls/apex/f?p=100:11::::P11_QUESTION_ID:1417403971710
Verwenden Sie ein Drittanbieter-Tool wie SQL Data Examiner , das Oracle-Datenbanken vergleicht und Unterschiede anzeigt.
Es wird nicht schnell sein und es wird eine Menge für Sie geben (es sei denn, Sie generieren die SQL aus user_tab_columns), aber ich verwende hier, wenn ich zwei Tabellen zeilenweise und spaltenweise miteinander vergleichen muss. Säule.
Die Abfrage gibt alle Zeilen zurück
(gemeinsame identische Zeilen werden ausgeschlossen).
"PK" ist die Spalte (n), aus der sich Ihr Primärschlüssel zusammensetzt. "A" enthält A, wenn die aktuelle Zeile in Tabelle1 vorhanden ist. "B" enthält B, falls die aktuelle Zeile vorhanden ist existiert in table2.
select pk
,decode(a.rowid, null, null, 'A') as a
,decode(b.rowid, null, null, 'B') as b
,a.col1, b.col1
,a.col2, b.col2
,a.col3, b.col3
,...
from table1 a
full outer
join table2 b using(pk)
where decode(a.col1, b.col1, 1, 0) = 0
or decode(a.col2, b.col2, 1, 0) = 0
or decode(a.col3, b.col3, 1, 0) = 0
or ...;
Edit Beispielcode hinzugefügt, um den in Kommentar beschriebenen Unterschied anzuzeigen. Immer wenn einer der Werte NULL enthält, ist das Ergebnis unterschiedlich.
with a as(
select 0 as col1 from dual union all
select 1 as col1 from dual union all
select null as col1 from dual
)
,b as(
select 1 as col1 from dual union all
select 2 as col1 from dual union all
select null as col1 from dual
)
select a.col1
,b.col1
,decode(a.col1, b.col1, 'Same', 'Different') as approach_1
,case when a.col1 <> b.col1 then 'Different' else 'Same' end as approach_2
from a,b
order
by a.col1
,b.col1;
col1 col1_1 approach_1 approach_2
==== ====== ========== ==========
0 1 Different Different
0 2 Different Different
0 null Different Same <---
1 1 Same Same
1 2 Different Different
1 null Different Same <---
null 1 Different Same <---
null 2 Different Same <---
null null Same Same
Die Verwendung des minus
-Operators funktionierte, aber auch die Ausführung dauerte länger, was nicht akzeptabel war. Ich habe eine ähnliche Anforderung an die Datenmigration und habe dafür den Operator NOT IN
verwendet. Die geänderte Abfrage lautet:
select *
from A
where (emp_id,emp_name) not in
(select emp_id,emp_name from B)
union all
select * from B
where (emp_id,emp_name) not in
(select emp_id,emp_name from A);
Diese Abfrage wurde schnell ausgeführt. Sie können auch eine beliebige Anzahl von Spalten in der Auswahlabfrage hinzufügen. Der einzige Haken ist, dass beide Tabellen genau dieselbe Tabellenstruktur haben sollten, damit diese ausgeführt werden kann.
SELECT *
FROM (SELECT table_name, COUNT (*) cnt
FROM all_tab_columns
WHERE owner IN ('OWNER_A')
GROUP BY table_name) x,
(SELECT table_name, COUNT (*) cnt
FROM all_tab_columns
WHERE owner IN ('OWNER_B')
GROUP BY table_name) y
WHERE x.table_name = y.table_name AND x.cnt <> y.cnt;
Vollständige äußere Verknüpfung verwendet - Wird jedoch nicht angezeigt, wenn keine Übereinstimmung vorliegt.
SQL> desc aaa - es ist eine Tabelle Name Null? Art
A1 NUMMER B1 VARCHAR2 (10)
SQL> desc aaav -es a view Name Null? Art
A1 NUMMER B1 VARCHAR2 (10)
SQL> Wählen Sie a.column_name, b.column_name unter dba_tab_columns einen vollständigen äußeren Join aus. Dba_tab_columns b unter a.column_name = b.column_name wobei a.TABLE_NAME = 'AAA' und B.table_name = 'AAAV';
COLUMN_NAME COLUMN_NAME
A1 A1 B1 B1