假设我有两个表,t1和t2,它们的布局相同但可能包含不同的数据。
区分这两个表的最佳方法是什么?
答案 0 :(得分:50)
试试这个:
(select * from T1 minus select * from T2) -- all rows that are in T1 but not in T2
union all
(select * from T2 minus select * from T1) -- all rows that are in T2 but not in T1
;
没有外部工具。 union all
没有性能问题。
答案 1 :(得分:13)
您可以尝试使用设置操作:MINUS
和INTERSECT
请点击此处了解更多详情: http://oreilly.com/catalog/mastorasql/chapter/ch07.html
答案 2 :(得分:5)
答案 3 :(得分:2)
对于这类问题,我认为你必须对你正在寻找的东西非常具体,因为有很多方法可以解释它和许多不同的方法。如果你的问题不能保证的话,有些方法会变得太大了。
在最简单的层面上,“表数据是否完全相同?”,您可能会尝试通过简单的计数比较来回答这些数据,然后再转向更复杂的事情。
在比例的另一端,“显示每个表中的行,而另一个表中没有等效的行”或“向我显示行具有相同的标识键但数据值不同”。
如果您确实想要将表A与表B同步,那么使用MERGE命令可能相对简单。
答案 4 :(得分:2)
您可以尝试dbForge Data Compare for Oracle ,一个免费的 GUI工具进行数据比较和同步,可以对所有数据库或部分数据库执行这些操作。
答案 5 :(得分:2)
快速解决方案:
SELECT * FROM TABLE1
MINUS
SELECT * FROM TABLE2
没有记录显示...
答案 6 :(得分:1)
如果您有一些钱可用,请使用PowerDIFF for Oracle工具:http://www.orbit-db.com。它提供了许多比较选项,可以很好地完成这些类型的工作。
答案 7 :(得分:0)
select * from table1 where table1.col1 in
(select table2.col1 from table2)
假设col1
是主键列,这将使table1
列中的所有行都与table2
列1相对应。
select * from table1 where table1.col1 not in
(select table2.col1 from table2)
希望这有帮助
答案 8 :(得分:0)
尝试:
select distinct T1.id
from TABLE1 T1
where not exists (select distinct T2.id
from TABLE2 T2
where T2.id = T1.id)
使用sql oracle 11g +
答案 9 :(得分:0)
除了提供的其他一些答案外,如果您想查看表结构与可能具有相似但不同结构的表之间的差异,则可以通过多种方式来做到这一点:
首先-如果使用Oracle SQL Developer,则可以在两个表上都运行一个describe来进行比较:
descr TABLE_NAME1
descr TABLE_NAME2
第二-对于具有很多列的较大表,第一个解决方案可能并不理想。如果您只想查看两个表之间的数据差异,那么正如其他几个人所提到的,使用SQL Minus运算符应该可以完成这项工作。
第三-如果您正在使用Oracle SQL Developer,并且想要使用不同的模式比较两个表的表结构,则可以执行以下操作:
第四-如果要比较的两个表的表具有更多的列,处于同一模式,不需要比较两个以上的表,并且不希望使用DESCR命令进行直观比较您可以使用以下内容比较表结构中的差异:
select
a.column_name || ' | ' b.column_name,
a.data_type || ' | ' b.data_type,
a.data_length || ' | ' b.data_length,
a.data_scale || ' | ' b.data_scale,
a.data_precision || ' | ' b.data_precision
from
user_tab_columns a,
user_tab_columns b
where
a.table_name = 'TABLE_NAME1'
and b.table_name = 'TABLE_NAME2'
and (
a.data_type <> b.data_type or
a.data_length <> b.data_length or
a.data_scale <> b.data_scale or
a.data_precision <> b.data_precision
)
and a.column_name = b.column_name;
答案 10 :(得分:0)
我使用Oracle SQL开发人员将表导出为CSV格式,然后使用WinMerge进行了比较。
答案 11 :(得分:0)
尝试一下
更改会话集“ _convert_set_to_join” = true;
另一种替代方法是手动重写SQL查询(用NOT IN子查询代替减号运算符)可证明执行时间缩短了30%。
select *
from A
where (col1,col2,?) not in
(select col1,col2,? from B)
union all
select * from B
where (col1,col2,?) not in
(select col1,col2,? from A);
我从这篇帖子click here引荐
答案 12 :(得分:0)
下面是我的解决方案-考虑到差异表可以有重复的行。接受的答案没有考虑到这一点,如果重复,将会给您错误的结果。我正在通过使用row_number()对它们进行编号,然后比较编号的行来照顾重复的行:
-- TEST TABLES
create table t1 (col_num number,col_date date,col_varchar varchar2(400));
create table t2 (col_num number,col_date date,col_varchar varchar2(400));
-- TEST DATA
insert into t1 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am in both');
insert into t2 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am in both');
insert into t1 values (null,null,'I am in both with nulls');
insert into t2 values (null,null,'I am in both with nulls');
insert into t1 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am in T1 only');
insert into t2 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am in T2 only');
insert into t1 values (null,null,'I am in T1 only with nulls');
insert into t2 values (null,null,'I am in T2 only with nulls');
insert into t1 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am twice in T1 but not in T2');
insert into t1 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am twice in T1 but not in T2');
insert into t2 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am twice in T2 but not in T1');
insert into t2 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am twice in T2 but not in T1');
insert into t1 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am twice in T1 and once in T2');
insert into t1 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am twice in T1 and once in T2');
insert into t2 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am twice in T1 and once in T2');
insert into t2 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am twice in T2 and once in T1');
insert into t2 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am twice in T2 and once in T1');
insert into t1 values (1,TO_DATE ('01.JAN.3000 00:00:00', 'DD.MON.YYYY HH24:MI:SS'),'I am twice in T2 and once in T1');
-- THE DIFF
-- All columns need to be named in the partition by clause, it is not possible to just say 'partition by *'
-- The column used in the order by clause does not matter in terms of functionality
(
select 'In T1 but not in T2' diff,s.* from (
select row_number() over (partition by col_num,col_date,col_varchar order by col_num) rn,t.* from t1 t
minus
select row_number() over (partition by col_num,col_date,col_varchar order by col_num) rn,t.* from t2 t
) s
) union all (
select 'In T2 but not in T1' diff,s.* from (
select row_number() over (partition by col_num,col_date,col_varchar order by col_num) rn,t.* from t2 t
minus
select row_number() over (partition by col_num,col_date,col_varchar order by col_num) rn,t.* from t1 t
) s
);