Как сравнить две таблицы столбец за столбцом в oracle

У меня есть две похожие таблицы в Oracle в двух разных базах данных. Например: мое имя таблицы-EMPLOYEE, а первичный ключ-employee id. Та же таблица с теми же столбцами(скажем, 50 столбцов-это avlbl в двух базах данных и две базы данных связаны.

Я хочу сравнить эти две таблицы столбец за столбцом и выяснить, какие записи не совпадают. мне нужен конкретный столбец в каждой строке в двух таблицах, которые не совпадают.

6 ответов


select *
from 
(
( select * from TableInSchema1
  minus 
  select * from TableInSchema2)
union all
( select * from TableInSchema2
  minus
  select * from TableInSchema1)
)

должен сделать трюк, если вы хотите решить эту проблему с помощью запроса


в качестве альтернативы, которая экономит от полного сканирования каждой таблицы дважды, а также дает вам простой способ сказать, какая таблица имела больше строк с комбинацией значений, чем другая:

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

кредит идет здесь: http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:1417403971710


попробуйте использовать сторонний инструмент, например SQL Data Examiner который сравнивает базы данных Oracle и показывает вам различия.


это будет не быстро, и вам будет много нужно ввести (если вы не создадите SQL из user_tab_columns), но вот что я использую, когда мне нужно сравнить две таблицы строка за строкой и столбец за столбцом.

запрос вернет все строки

  • существует в table1, но не в table2
  • существует в table2, но не в table1
  • существует в обеих таблицах, но имеет по крайней мере один столбец с другим значение

(общей идентичные строки будут исключены).

" PK " - это столбец(ы), которые составляют ваш первичный ключ. "a" будет содержать A, если данная строка существует в таблице 1. "b" будет содержать B, если данная строка существует в таблице 2.

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

редактировать Добавлен пример кода, чтобы показать разницу, описанную в комментарии. Всякий раз, когда одно из значений содержит NULL, результат будет отличаться.

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       

С помощью minus оператор работал, но также требовалось больше времени для выполнения, что было неприемлемо. У меня есть аналогичное требование для миграции данных, и я использовал NOT IN оператор для этого. Измененный запрос :

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

этот запрос выполняется быстро. Также вы можете добавить любое количество столбцов в запросе Select. Только уловка заключается в том, что обе таблицы должны иметь одинаковую структуру таблиц для выполнения этого.


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;