Как сравнить две таблицы столбец за столбцом в 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;