以下存储过程从程序上看没什么问题,但是我来描述 一下问题: 
1)TA723008 简称A表,TA723003_prepare简称B表。 
2)A表里面有4千万条以上的数据,B表里面有1万条以上的数据,现在要对A表的某字段更新,匹配条件是A表中的日期为20071231之前的。然后就是拿A表中的某个字段去关联B表的字段,得到B表中的中文名然后更新到A表中去。 
可是因为客观原因,不可能让一个存储过程跑一个晚上还在更新,因为按照以下的程序是一个笛卡尔乘积,拿一个表的全表扫描去匹配另一个表的全表扫描。 
3)程序详解:逐条更新,然后通过计数器每更新1万条就commit一次。 
希望有人能提出有建设性的方案来解决笛卡尔乘积 然后又能满足以上所说功能。不甚感激!!!! 
PROCEDURE R_MOVE_TA723008(OI_FLAG OUT INTEGER, --0 成功, -1 失败 
                            OS_MESG OUT VARCHAR2 --出错详细信息 
                            ) IS 
    VI_COUNT    INTEGER := 0; --计数器 
    VI_COUNT_all INTEGER := 0; --计数器 
    CURSOR CUR_TA723008 IS 
      SELECT ROWID, T.* 
        FROM BIFT.TA723008 T 
      WHERE T.TA723008002 <= '20071231' 
        AND t.ta723008015 IS NULL; 
  
  BEGIN 
    OI_FLAG := 0; 
    OS_MESG := '更新开始'; 
  
    FOR VT_TA723008 IN CUR_TA723008 LOOP 
      UPDATE TA723008 
        SET TA723008015 = (SELECT TA723003007 
                              FROM TA723003_PREPARE 
                            WHERE TA723003_PREPARE.TA723003005 = TA723008009 
                              AND ROWNUM = 1) 
      WHERE TA723008.ROWID = VT_TA723008.ROWID; 
    
      VI_COUNT    := VI_COUNT + 1; 
      VI_COUNT_all := VI_COUNT_all + 1; 
      IF (VI_COUNT >= 10000) THEN 
        COMMIT; 
        VI_COUNT := 0; 
      END IF; 
    END LOOP; 
      OI_FLAG := 0; 
    OS_MESG := '更新结束'; 
    COMMIT; 
  EXCEPTION 
    WHEN OTHERS THEN 
      OI_FLAG := 1; 
      OS_MESG := SUBSTRB(OS_MESG || '时出错! 错误代码:' || SQLCODE || ',错误信息:' || 
                        SQLERRM, 
                        1, 
                        400); 
    
      RETURN; 
    
  END R_MOVE_TA723008;

解决方案 »

  1.   

    *认为应该没办法的路过,,,
    毕竟你的基数太大,,,
    而从各个角度上,我们能做的,,也只是想办法避免你所说的需求
    方法1
    缩减必须全部更新的行数,也就是说,,我们可以想办法分几个晚上去更新- -
    方法2
    在使用到数据的时候再使用程序去进行以上处理,,,在调用的存储过程或程序上,前面增加更新语句,当然首先得在A表上增加一个bit字段确认是否已经被更新,,,然后相信程序运行个几个月后,,我们需要一次性的更新量已经减少很多了- -至于其他,,就只有看你的项目的特殊性,,看有没有更独特的办法了
      

  2.   

    Oracle格式?若是SQL SERVER有偿,可联系ME