J'ai deux tables similaires dans Oracle dans deux bases de données différentes. Par exemple: mon nom de table est EMPLOYEE et la clé primaire est id d’employé. La même table avec les mêmes colonnes (par exemple, 50 colonnes sont disponibles dans deux bases de données et deux bases de données sont liées.
Je veux comparer ces deux tables, colonne par colonne, et trouver quels enregistrements ne correspondent pas. Je veux la colonne spécifique dans chaque ligne dans deux tables qui ne correspondent pas.
select *
from
(
( select * from TableInSchema1
minus
select * from TableInSchema2)
union all
( select * from TableInSchema2
minus
select * from TableInSchema1)
)
devrait faire l'affaire si vous voulez résoudre ce problème avec une requête
En guise d'alternative, qui économise deux fois l'analyse complète de chaque table et vous permet également de déterminer facilement quelle table comporte plus de lignes avec une combinaison de valeurs que l'autre:
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
Le crédit va ici: http://asktom.Oracle.com/pls/apex/f?p=100:11:::::P11_QUESTION_ID:1417403971710
Essayez d'utiliser un outil tiers, tel que SQL Data Examiner , qui compare les bases de données Oracle et vous montre les différences.
Ce ne sera pas rapide et vous aurez beaucoup de choses à taper (sauf si vous générez le code SQL à partir de user_tab_columns), mais voici ce que j'utilise lorsque je dois comparer deux tables colonne.
La requête retournera toutes les lignes qui
(les lignes communes identiques seront exclues).
"PK" est la ou les colonnes qui composent votre clé primaire . "A" contiendra A si la ligne actuelle existe dans table1 . "B" contiendra B si la ligne actuelle existe dans 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 Exemple de code ajouté pour montrer la différence décrite dans le commentaire . Chaque fois que l'une des valeurs contient NULL, le résultat sera différent.
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
L'utilisation de l'opérateur minus
fonctionnait, mais l'exécution prenait plus de temps, ce qui était inacceptable. J'ai des exigences similaires pour la migration des données et j'ai utilisé l'opérateur NOT IN
pour cela. La requête modifiée est:
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);
Cette requête a été exécutée rapidement. Vous pouvez également ajouter un nombre quelconque de colonnes dans la requête de sélection. Le seul problème est que les deux tables devraient avoir exactement la même structure de table pour que cela soit exécuté.
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;