现在需要完成一个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;

解决方案 »

  1.   

    如果两个表的行数不相等的话,那做MINUS后难道得出的结果有可能为0吗???
    感觉查出两个表的记录数不相等的话就没有必要做minus了....
    但是如果两个表的行数相等了,也并不代表两个表的数据就完全一样吧.
    所以我觉得:
    i)当两个表的行数相等时,加上minus,确定两个表的数据是否完全一致.
    ii)当两个表的行数不相等时,就可以确定两个表的数据肯定不一致了...
      

  2.   

    说少了点东西:
    MINUS操作的最好两个表都分别做一下吧.有可能A表是B表的子结果集....如果A MINUS B得出的结果也是为0吧....
      

  3.   

    tjinjie 大虾,俺的实现思路应当是和你一致的但是我想确认这是否是最佳效率的 sql
    再指点一下啊
      

  4.   

    不知道这样做效率会怎样:
    两个表各建一个虚拟列:生成hashcode码(把这两个表的每一个字段都拼接进去,生成一个hashcode字段),每次比较就只比较这个hashcode字段就可以了.
    而且可以用Exists语法来比较,这样应该会比MINUS要快.
    还有直接的去比较这两个hashcode字段的值,不要COUNT(*)的操作....
    呵呵,我也不知道这样做效率行不行.....
      

  5.   

    又改了一把,加上目标表对源表的差集判断
    前面的逻辑是有问题的正确的逻辑是
    正确的做法是:
    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;
      

  6.   

    declare v_count number;bgein
     select count(rowid) 
     into v_count
     from
       (select * from a
        union
        select * from b);end;上面的结果,如果检索出来的记录数和两个表的记录都
    相同,不就可以证明,两个表是一样的?
      

  7.   

    "
    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}
    是什么结果啊.难道两次全量扫描表不可避免,郁闷中啊
      

  8.   

    实话告诉你们
    日本人是导出到Excel里再比较每个字段是否相等的
    我很无奈,不是我设计的,唉
      

  9.   

    要是谁能开发一个beyondCompare那样的比较数据库表内容的东东就好了
    期待大侠的表现了
      

  10.   

    如果有PL/SQL.那就用PL/SQL来比较吧