10
votes

Comment comparer la colonne de deux tables par colonne dans Oracle

J'ai deux tables similaires à Oracle dans deux bases de données différentes. Par exemple: mon nom de table est l'employé et la clé primaire est l'ID d'employé. La même table avec les mêmes colonnes (par exemple 50 colonnes est AVLBL dans deux bases de données et deux bases de données sont liées.

Je souhaite comparer ces deux tables colonne par colonne et découvrez quels enregistrements ne correspondent pas. Je veux la colonne spécifique de chaque rangée dans deux tables qui ne correspondent pas.


1 commentaires

Pourquoi cette réponse est-elle acceptable? Cela ne fait pas la partie la plus difficile qui consiste à spécifier la colonne qui ne correspond pas.


7 Réponses :


18
votes
select *
from 
(
( select * from TableInSchema1
  minus 
  select * from TableInSchema2)
union all
( select * from TableInSchema2
  minus
  select * from TableInSchema1)
)
should do the trick if you want to solve this with a query

4 commentaires

+1 Vous pouvez également souhaiter ajouter une colonne à chaque requête pour indiquer où les données sont venues. Par exemple: "Sélectionnez 1 schema1or2, tableinschema1. * De tableinschema1 moins ...". Ensuite, à l'ordre final par certaines valeurs et cette nouvelle colonne, par exemple "commande par 2, 3, 4, 5, 1 desc". Ensuite, vous obtiendrez (probablement) des rangées liées les unes à côté de l'autre, et il sera évident ce qui est différent et différent de ce qui manque.


@jon, suggérez-vous de choisir 2 schema1or2, * pour l'autre moitié du moins? Si vous ajoutez une constante, chaque ligne ne correspond pas. Essayez-le avec la même table. Sélectionnez 1 Inschema1or2, a. * de Attribs A moins Select 2, b. * de Attribs B <- Conspose à chaque rangée. Et vous avez deux upvotes qui sont effrayants.


@Stephanie, je veux dire ajouter "Sélectionnez 1" aux deux premières requêtes et ajoutez "Sélectionnez 2" aux deux dernières requêtes.


Je voudrais une nouvelle réponse. Il suffit de marquer cw afin qu'il ne ressemble pas à un vol de représentant. Lorsque vous obtenez plus de représentant, éditez la réponse, c'est une bonne suggestion.



0
votes

Essayez d'utiliser un outil tiers partis, tel que examinateur de données SQL qui compare les bases de données Oracle et vous montre Différences.


0 commentaires

6
votes

Au fur et à mesure de la numérisation complète de chaque table et vous donne également un moyen facile de dire quelle table avait 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


0 commentaires

1
votes

Ce ne sera pas rapide, et il y aura beaucoup pour vous de taper (sauf que vous ne produisiez la SQL à partir d'user_tab_columns), mais voici ce que j'utilise lorsque j'ai besoin de comparer deux tables à la ligne et de la colonne -by-colonne.

La requête retournera toutes les lignes que p>

  • existe dans le tableau1 mais pas dans le tableau2 li>
  • existe dans le tableau2 mais pas dans le tableau1 li>
  • existe dans les deux tables, mais avoir au moins une colonne avec une valeur différente li> ul>

    (les lignes identiques communes seront exclues). p>

    "pk" est la ou les colonnes qui constituent votre clé primaire. "A" contiendra un si le rang actuel existe dans le tableau1. "B" contiendra B si la rangée actuelle existe dans le tableau2. p> xxx pré>

    edit forte> Exemple de code ajouté pour afficher la différence décrite dans le commentaire. Chaque fois que l'une des valeurs contient NULL, le résultat sera différent. P>

    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       
    


3 commentaires

Salut Ronnis, pouvez-vous décrire ce que la commande de décodage fait dans votre code?


C'est un moyen de contourner le problème avec NULLS. Si, par exemple, Col1 "était null dans l'une des tables, je ne détecterais pas l'inadéquation en utilisant" A.Col1 <> B.Col1 ". J'exploite le fait que le décodage traite NULL comme égal à NULL.


Cela pourrait être assez rapide. Je viens de le faire sur 12 schémas, avec un total de 500 tables, un total de 3 millions de lignes, sur une liaison de base de données, et il a fini de comparer toutes les tables (et synchronisant la cible) en moins de 10 minutes.



0
votes

Utilisation de l'opérateur moins code> fonctionnait, mais il prenait également plus de temps pour exécuter ce qui n'était pas acceptable. J'ai un type similaire à la migration de données et j'ai utilisé le pas dans l'opérateur code> pour cela. La requête modifiée est la suivante:

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); 


0 commentaires

0
votes
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;

0 commentaires

0
votes

Un joint externe total utilisé - mais il ne montrera pas - si ce n'est pas assorti -

SQL> Desc Aaa - c'est une table Nom NULL? Tapez


Numéro A1 B1 Varchar2 (10)

SQL> Desc Aaav -its une vue Nom NULL? Tapez


Numéro A1 B1 Varchar2 (10)

SQL> SELECT A.COLUMN_NAME, B.Column_columns de dba_tab_columns Un join externe complet dba_tab_columns b sur a.column_name = B.Column_name While aaa_name = 'AAA' et B.Table_Name = 'AAAV';

Nom de colonne colonne_name


A1 A1 B1 B1


1 commentaires

Réponse susceptible malgré son faible formatage et sa logique car Joindre extérieur complet n'a pas été mentionné dans une autre réponse et une alternative vraiment précieuse dans certains cas, en particulier lorsqu'il est utilisé comme Natural complet rejoindre . Ce blogvost l'élabore plus en détail: blog.jooq.org/2020/08/05/...