比较两个表数据完全一致的sql

jayli426 2008-06-05 03:05:26
现在需要完成一个sql,比较两个表数据完全一致(两个表结构肯定是一致的).
我现在是通过minus功能来完成
如果 两个表 minus的结果等于0,那么证明这两个表完全一致
当然之前肯定还做一个两个表行数的比较,首先要保证两个表行数一致的,
感觉这样写出来的东东代码是比较少,但是不知效率如何 ,请大虾指点一下才好啊
下面是整个存储过程,已经调试通过了,大虾看看如何啊


create or replace procedure compareTableData(srcTable in
varchar2 , destTable in varchar2 , oi_return out int)
is
--源表格
src_table varchar2(32);
--目标表格
dest_Table varchar2(32);
--源表格行数
src_table_count int;
--目标表格函数
dest_table_count int;
--两个表格数据(即结果集)之间的差集的个数
minus_count int;

selectSrcSql varchar2(100);
selectDestSql varchar2(100);
selectMinusSql varchar2(200);
--错误描述
v_err_desc varchar2(100);
begin
oi_return :=0;
dbms_output.put_line(oi_return);

src_table := srcTable;

dest_Table := destTable;


--构建查询源表行数的动态sql
selectSrcSql:=' select count(*) from '||src_table;

DBMS_OUTPUT.PUT_LINE(selectSrcSql);

--执行查询源表行数的动态sql
execute immediate selectSrcSql Into src_table_count;

--构建查询源目标行数的动态sql
selectDestSql:=' select count(*) from ' ||dest_Table;

DBMS_OUTPUT.PUT_LINE(selectDestSql);

--执行查询源目标行数的动态sql
execute immediate selectDestSql Into dest_table_count;

--构建查询两个表差集行数的动态sql
selectMinusSql:='select count(*) from (
select * from ' ||src_table||
' minus
select * from ' ||dest_table|| ')';

DBMS_OUTPUT.PUT_LINE(selectMinusSql);

--如果表格行数不一致,那么证明两个表结果集肯定不一致
if(src_table_count!=dest_table_count)
then
oi_return:= src_table_count-dest_table_count;
else
--执行查询两个表差集行数的动态sql
execute immediate selectMinusSql into minus_count;
--返回差集个数,如果是0,那么证明两个表结果集肯定一致 ,反之不一致
oi_return := minus_count;
end if;

EXCEPTION
WHEN OTHERS THEN
v_err_desc := 'Error' || TO_CHAR(SQLCODE) || ':' || SQLERRM;
oi_return:= SQLCODE;
DBMS_OUTPUT.PUT_LINE(v_err_desc);
end compareTableData;
...全文
2265 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
8193102 2008-07-08
  • 打赏
  • 举报
回复
如果有PL/SQL.那就用PL/SQL来比较吧
loveflying000 2008-07-07
  • 打赏
  • 举报
回复
要是谁能开发一个beyondCompare那样的比较数据库表内容的东东就好了
期待大侠的表现了
loveflying000 2008-07-07
  • 打赏
  • 举报
回复
实话告诉你们
日本人是导出到Excel里再比较每个字段是否相等的
我很无奈,不是我设计的,唉
zero8500 2008-07-03
  • 打赏
  • 举报
回复
路过
jayli426 2008-06-10
  • 打赏
  • 举报
回复
"
declare

v_count number;

bgein
select count(rowid)
into v_count
from
(select * from a
union
select * from b);

end;

上面的结果,如果检索出来的记录数和两个表的记录都
相同,不就可以证明,两个表是一样的?
"

大虾,这个也是不严密的啊

可以考虑A{a,b,c}
union
B{a,b,b}
是什么结果啊.

难道两次全量扫描表不可避免,郁闷中啊
haru 2008-06-09
  • 打赏
  • 举报
回复
declare

v_count number;

bgein
select count(rowid)
into v_count
from
(select * from a
union
select * from b);

end;

上面的结果,如果检索出来的记录数和两个表的记录都
相同,不就可以证明,两个表是一样的?
oraclelogan 2008-06-05
  • 打赏
  • 举报
回复
安静的路过。
jayli426 2008-06-05
  • 打赏
  • 举报
回复
又改了一把,加上目标表对源表的差集判断
前面的逻辑是有问题的

正确的逻辑是
正确的做法是:
1、先判断两个表行数是否相同,如果相同的继续往下走。
2、用源表 minus 目标表,看返回的行数是否为0,如果为0则继续往下走。
3、用目标表 minus 源表,看返回的行数是否为零,如果为零则证明两个表相同。


create or replace procedure compareTableData(srcTable in
varchar2 , destTable in varchar2 , oi_return out int)
is
--源表格
src_table varchar2(32);
--目标表格
dest_Table varchar2(32);
--源表格行数
src_table_count int;
--目标表格函数
dest_table_count int;
--两个表格数据(即结果集)之间的差集的个数
minus_count int;

selectSrcSql varchar2(100);
selectDestSql varchar2(100);
selectSrcMinusDestSql varchar2(200);
selectDestMinusSrcSql varchar2(200);
--错误描述
v_err_desc varchar2(100);
begin
oi_return :=0;
dbms_output.put_line(oi_return);

src_table := srcTable;

dest_Table := destTable;


--构建查询源表行数的动态sql
selectSrcSql:=' select count(*) from '||src_table;

DBMS_OUTPUT.PUT_LINE(selectSrcSql);

--执行查询源表行数的动态sql
execute immediate selectSrcSql Into src_table_count;

--构建查询源目标行数的动态sql
selectDestSql:=' select count(*) from ' ||dest_Table;

DBMS_OUTPUT.PUT_LINE(selectDestSql);

--执行查询源目标行数的动态sql
execute immediate selectDestSql Into dest_table_count;

--构建查询源表和目标表差集行数的动态sql
selectSrcMinusDestSql:='select count(*) from (
select * from ' ||src_table||
' minus
select * from ' ||dest_table|| ')';

DBMS_OUTPUT.PUT_LINE(selectSrcMinusDestSql);


--构建查询目标表和源表差集行数的动态sql
selectDestMinusSrcSql:='select count(*) from (
select * from ' ||dest_table||
' minus
select * from ' ||src_table|| ')';

DBMS_OUTPUT.PUT_LINE(selectDestMinusSrcSql);

--如果表格行数不一致,那么证明两个表结果集肯定不一致
if(src_table_count!=dest_table_count)
then
oi_return:= src_table_count-dest_table_count;
else
--执行查询源表和目标表差集行数的动态sql
execute immediate selectSrcMinusDestSql into minus_count;
--如果差集为0,表明源表集合中元素在目标表中都存在,但是并不能说明源表和目标表集合完全一致,
--因为源表中可能有重复元素,导致差集也为0的结果
if(minus_count=0)
then
--执行查询目标表和源表差集行数的动态sql
execute immediate selectDestMinusSrcSql into minus_count;
end if;
--返回差集个数,如果是0,那么证明两个表结果集肯定一致 ,反之不一致
oi_return := minus_count;
end if;

EXCEPTION
WHEN OTHERS THEN
v_err_desc := 'Error' || TO_CHAR(SQLCODE) || ':' || SQLERRM;
oi_return:= SQLCODE;
DBMS_OUTPUT.PUT_LINE(v_err_desc);
end compareTableData;
tjinjie 2008-06-05
  • 打赏
  • 举报
回复
不知道这样做效率会怎样:
两个表各建一个虚拟列:生成hashcode码(把这两个表的每一个字段都拼接进去,生成一个hashcode字段),每次比较就只比较这个hashcode字段就可以了.
而且可以用Exists语法来比较,这样应该会比MINUS要快.
还有直接的去比较这两个hashcode字段的值,不要COUNT(*)的操作....
呵呵,我也不知道这样做效率行不行.....
jayli426 2008-06-05
  • 打赏
  • 举报
回复
tjinjie 大虾,俺的实现思路应当是和你一致的

但是我想确认这是否是最佳效率的 sql
再指点一下啊
tjinjie 2008-06-05
  • 打赏
  • 举报
回复
说少了点东西:
MINUS操作的最好两个表都分别做一下吧.有可能A表是B表的子结果集....如果A MINUS B得出的结果也是为0吧....
tjinjie 2008-06-05
  • 打赏
  • 举报
回复
如果两个表的行数不相等的话,那做MINUS后难道得出的结果有可能为0吗???
感觉查出两个表的记录数不相等的话就没有必要做minus了....
但是如果两个表的行数相等了,也并不代表两个表的数据就完全一样吧.
所以我觉得:
i)当两个表的行数相等时,加上minus,确定两个表的数据是否完全一致.
ii)当两个表的行数不相等时,就可以确定两个表的数据肯定不一致了...

17,090

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧