Как сравнить две таблицы столбец за столбцом в оракуле - PullRequest
8 голосов
/ 20 октября 2010

У меня есть две одинаковые таблицы в oracle в двух разных базах данных. Например: мое имя таблицы - EMPLOYEE, а первичный ключ - идентификатор сотрудника. Одна и та же таблица с одинаковыми столбцами (скажем, 50 столбцов доступны в двух базах данных, и две базы данных связаны между собой.

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

Ответы [ 6 ]

15 голосов
/ 20 октября 2010
select *
from 
(
( select * from TableInSchema1
  minus 
  select * from TableInSchema2)
union all
( select * from TableInSchema2
  minus
  select * from TableInSchema1)
)

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

4 голосов
/ 22 октября 2010

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

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

1 голос
/ 03 декабря 2010

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

Запрос вернет все строки, которые

  • Существует в таблице 1, но отсутствует в таблице 2
  • Существует в таблице2, но отсутствует в таблице1
  • Существует в обеих таблицах, но имеет хотя бы один столбец с другим значением

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

"PK" - это столбец (столбцы), которые составляют ваш первичный ключ. «a» будет содержать A, если существующая строка существует в table1. «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       
1 голос
/ 20 октября 2010

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

0 голосов
/ 04 мая 2015
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 голосов
/ 27 января 2015

Использование оператора 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); 

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...