2010-10-20 49 views
8

Tôi có hai bảng tương tự trong oracle trong hai cơ sở dữ liệu khác nhau. Ví dụ: tên bảng của tôi là EMPLOYEE và khóa chính là id của nhân viên. Cùng một bảng với cùng một cột (nói 50 cột là avlbl trong hai cơ sở dữ liệu và hai cơ sở dữ liệu được liên kết.Cách so sánh hai cột bảng theo cột trong oracle

Tôi muốn so sánh hai cột này theo cột và tìm ra bản ghi nào không khớp. trong mỗi hàng trong hai bảng mà không phải là phù hợp.

+1

Tại sao câu trả lời đó lại được chấp nhận? Nó không làm phần khó nhất là xác định cột không khớp. –

Trả lời

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

nên làm các trick nếu bạn muốn giải quyết điều này với một truy vấn

+4

+1 Bạn cũng có thể muốn thêm một cột vào mỗi truy vấn để cho biết dữ liệu đến từ đâu. Ví dụ: "chọn 1 schema1Or2, TableInSchema1. * Từ TableInSchema1 trừ ...". Sau đó, theo thứ tự kết thúc bởi một số giá trị và cột mới đó, ví dụ: "order by 2, 3, 4, 5, 1 desc". Sau đó, bạn sẽ (có thể) nhận được các hàng liên quan bên cạnh nhau, và nó sẽ được rõ ràng những gì khác so với những gì còn thiếu. –

+0

@jon, bạn có đề xuất CHỌN 2 SCHEMA1or2, * cho nửa còn lại của dấu trừ không? nếu bạn thêm một hằng số thì mọi hàng sẽ không khớp nhau. Hãy thử nó với cùng một bảng. chọn 1 inSchema1or2, a. * từ attribs trừ đi 2, b. * từ attribs b <- yields mỗi hàng. Và bạn có hai upvotes đó là đáng sợ. –

+0

@Stephanie, ý tôi là thêm "select 1" vào hai truy vấn đầu tiên và thêm "select 2" vào hai truy vấn cuối cùng. –

1

Cố gắng sử dụng công cụ của bên thứ 3, chẳng hạn như SQL Data Examiner mà so sánh cơ sở dữ liệu Oracle và cho bạn thấy sự khác biệt.

3

Là một thay thế mà tiết kiệm khỏi quá trình quét đầy đủ mỗi bảng hai lần và cũng cung cấp cho bạn một cách dễ dàng để cho các bảng có nhiều hàng với sự kết hợp của các giá trị so với người kia:

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 

Credit goes here: http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:1417403971710

1

Nó sẽ không được nhanh chóng, và sẽ có rất nhiều để bạn gõ (trừ khi bạn tạo SQL từ user_tab_columns), nhưng đây là những gì tôi sử dụng khi tôi cần phải so sánh hai bảng hàng-by-hàng và cột- theo cột.

Các truy vấn sẽ trả lại tất cả các hàng mà

  • Tồn tại trong table1 nhưng không phải trong table2
  • Tồn tại trong table2 nhưng không phải trong table1
  • Tồn tại trong cả hai bảng, nhưng có ít nhất một cột với một giá trị khác nhau

(các hàng giống nhau thông thường sẽ bị loại trừ).

"PK" là (các) cột tạo nên khóa chính của bạn. "a" sẽ chứa A nếu hàng hiện tại tồn tại trong bảng 1. "b" sẽ chứa B nếu hàng hiện tại tồn tại trong bảng 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 ...; 

Sửa Added mã ví dụ để thấy sự khác biệt được mô tả trong nhận xét. Bất cứ khi nào một trong các giá trị chứa NULL, kết quả sẽ khác nhau.

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

Xin chào Ronnis, bạn có thể mô tả lệnh giải mã làm gì trong mã của bạn không? –

+1

Đó là một cách xung quanh vấn đề với null. Nếu ví dụ "col1" là null trong một trong các bảng, tôi sẽ không phát hiện sự không phù hợp bằng cách sử dụng "a.col1 <> b.col1". Tôi đang khai thác thực tế là DECODE xử lý NULL bằng NULL. – Ronnis

+0

Nó có thể đủ nhanh. Tôi đã thực hiện điều này trên 12 lược đồ, với tổng số 500 bảng, tổng cộng 3 triệu hàng, qua một liên kết cơ sở dữ liệu và hoàn thành so sánh tất cả các bảng (và đồng bộ hóa đích) trong chưa đầy 10 phút. –

0

Sử dụng toán tử minus đang hoạt động nhưng cũng mất nhiều thời gian hơn để thực thi không được chấp nhận. Tôi có một loại yêu cầu tương tự cho việc di chuyển dữ liệu và tôi đã sử dụng toán tử NOT IN cho điều đó. Truy vấn được sửa đổi là:

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

Truy vấn này được thực thi nhanh. Ngoài ra, bạn có thể thêm bất kỳ số lượng cột nào trong truy vấn chọn. Chỉ bắt là cả hai bảng phải có cấu trúc bảng giống nhau để thực hiện điều này.

0
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; 
Các vấn đề liên quan