需求是这样,现在有一张表, 我需要通过游标全部读取出来,  然后根据 第一个字段的值 分别做不同的操作,但是在做操作的时候,第一个字段必须按照一定的逻辑才能继续往下走 例子:
c1 c2    c3 .......
1  xxx   xxx
2  xxx   xxx
2  xxx   xxx
8  xxx   xxx逻辑是这样,读取出来的数据,第一条记录的C1 必须是 1 否则 不继续下去
如果第一条记录的 c1 是1 ,下来的第2条 ,第3条 的c1都可以是2 ,也就是说 区分值 2 可以出现很多次 只是需要出现在1后面然后,区分2 完了后的下一条记录的C1 必须是8 ,当遇到8的时候COMMIT
另外还有一种情况,8 也可以出现在 1 的 后面,但是只能出现一次,如果一旦出现8 ,那么 它下一条记录的c1 就必须是 1了 
也就是说 从1开始 一只到8 这个算一个业务遇到8 就提交事务, 比如 1 2 2 2 。。 8 还有 1 8 , 1 8   , 1 2 8, 这样都是正确的数据,如果出现 比如 1 1 ;  1 2 2 2 2 (没有8)  , 1 8 8 8 (多个8在一起) 这样都是错误的数据
请问下这种情况如何判断才好呢? 谢谢

解决方案 »

  1.   

    我的想法是,把C1 全部拿出来,然后用table类型的 变量存储,然后在判断 ,但是感觉也不好说明下,这个是要求用oracle 存储过程写 谢谢
      

  2.   

    希望楼主满意!
    create table tTestData(
      C1    Number,
      C2    Number,
      C3    Number,
      C4    Number
    );insert into tTestData(C1, C2, C3, C4)
    select 1, 100, 200, 0 from dual
    union all
    select 2, 100, 200, 0 from dual
    union all
    select 2, 100, 200, 0 from dual
    union all
    select 1, 100, 200, 1 from dual
    union all
    select 8, 100, 200, 0 from dual
    union all
    select 8, 100, 200, 1 from dual;
    Commit;create table tLogicPar(
      sStartValue   varchar2(20),   
      sAllowValue   varchar2(200),
      sExecuteSql   varchar(4000),
      sErrorMsg     varchar(2000),
      iLogicType    Integer,
      iOrder        Integer 
    );delete from tLogicPar;
    insert into tLogicPar(sStartValue, sAllowValue, sExecuteSql, sErrorMsg, iLogicType, iOrder)
    select '1', ',1,', '', '第一条记录必须是1', 0, 0 from dual
    union all
    select '1', ',2,8,', '你要的Sql', '1的后面只能是2和8', 1, 1 from dual
    union all
    select '2', ',2,8,', '你要的Sql', '2的后面只能是2和8', 1, 2 from dual
    union all
    select '8', ',1,', 'Commit', '8的后面只能是1', 1, 3 from dual;
    Commit;create or replace procedure PLogicCheck(iTestType number) is
      sCurrentValue varchar2(20);
      sAllowValue   varchar2(200);
      sExecuteSql   Varchar2(4000);
      sErrorMsg     Varchar2(2000);
      iRec          Number;
      iCheck        Number;
      eError        Exception;
    begin
      iRec:= 0;
      for CData in (select C1, C2, C3 from tTestData where C4 <= iTestType) loop
        iRec:= iRec + 1;
        -- 检查第一条记录是否是正确的起点
        if iRec =  1 then
          begin
            select sStartValue, sAllowValue, sExecuteSql, sErrorMsg
              into sCurrentValue, sAllowValue, sExecuteSql, sErrorMsg
              from tLogicPar
             where iLogicType = 0;        if Nvl(To_Char(CData.C1), 'Check') <> Nvl(sCurrentValue, 'NoCheck') then
              Dbms_Output.Put_Line(sErrorMsg);
              Raise eError;
            end if;
            
          exception  
            when No_Data_Found then
              Dbms_Output.Put_Line('没有找到逻辑检查起点!');
              Raise eError;
            when Too_Many_Rows then
              Dbms_Output.Put_Line('过多逻辑检查起点!');
              Raise eError;
            when Others then
              Dbms_Output.Put_Line('其他错误:' + SqlErrM);
              Raise eError;
          end;
        end if;
        -- 检查当前记录是否在上一记录的允许范围值之内
        if instr(sAllowValue, ',' || To_Char(CData.C1) || ',') <= 0 then
          Dbms_Output.Put_Line('第' || To_Char(iRec) || '条数据错误,当前值是' || To_Char(cData.C1) || 
                               ',上一条是' || sCurrentValue || ',' || sErrorMsg);
          Raise eError;
        end if;
        -- 检查通过未下一条语句的允许值、本条语句的执行语句、出错信息赋值
        begin
          select sStartValue, sAllowValue, sExecuteSql, sErrorMsg
            into sCurrentValue, sAllowValue, sExecuteSql, sErrorMsg
            from tLogicPar
           where sStartValue = To_Char(cData.C1)
             and iLogicType = 1;
          
          -- 执行Sql语句    
        
        exception 
          when No_Data_Found then
            Dbms_Output.Put_Line('没有找到' || To_Char(CData.C1) || '的逻辑检查设置!');
            Raise eError;
          when Too_Many_Rows then
            Dbms_Output.Put_Line('过多的' || To_Char(CData.C1) || '的逻辑检查设置!');
            Raise eError;
          when Others then
            Dbms_Output.Put_Line(To_Char(CData.C1) || ' 其他错误:' + SqlErrM);
            Raise eError;
        end;
      end loop;
      Dbms_Output.Put_Line('程序执行完毕,没有错误!');
    exception
      when eError then
        Null;
      when others then
        Dbms_Output.Put_Line('发现未知错误:' + SqlErrM);
    end;
    /
      

  3.   

    这是执行结果。
    SQL> exec PLogicCheck(0);  -- 正确
    程序执行完毕,没有错误!
    SQL> exec PLogicCheck(1);  -- 错误
    第4条数据错误,当前值是1,上一条是2,2的后面只能是2和8
      

  4.   

    如果只是1, 2, 8这几种情况的话可以这样写。
    create or replace procedure PLogicChk(iTestType number) is
      sPriorValue   varchar2(200);
      sAllowValue   varchar2(200);
      iRec          Number;
      eError        Exception;
    begin
      iRec:= 0;
      for CData in (select C1, C2, C3 from tTestData where C4 <= iTestType) loop
        iRec:= iRec + 1;
        if (iRec = 1) and (cData.C1 <> 1) then
          Dbms_Output.Put_Line('第一条记录必须是1');
          Raise eError;
        elsif (iRec = 1) and (cData.C1 = 1) then
         -- 执行Sql语句
        
         -- 为下一条允许值赋值
          sAllowValue:= ',2,8,';  
          sPriorValue:= To_Char(CData.C1); 
        else 
         -- 不是第一条数据
          -- 检查当前记录是否在上一记录的允许范围值之内
          if instr(sAllowValue, ',' || To_Char(CData.C1) || ',') <= 0 then
            Dbms_Output.Put_Line('第' || To_Char(iRec) || '条数据错误,当前值是' || To_Char(cData.C1) || 
                                 ',上一条是' || sPriorValue || ', ' || sPriorValue || '的后面只能是' ||
                                 Substr(Substr(sAllowValue, 2), 1, Length(Substr(sAllowValue, 2)) - 1));
            Raise eError;
          else
            -- 通过当前值执行Sql
            if CData.C1 = 1 then
              -- 执行你的Sql语句
              
              -- 为下一条允许值赋值
              sAllowValue:= ',2,8,';  
              sPriorValue:= To_Char(CData.C1); 
            elsif CData.C1 = 2 then
              -- 执行你的Sql语句          -- 为下一条允许值赋值
              sAllowValue:= ',2,8,';  
              sPriorValue:= To_Char(CData.C1); 
            elsif  CData.C1 = 8 then
              -- 执行你的Sql语句
              Commit;
              -- 为下一条允许值赋值
              sAllowValue:= ',1,';  
              sPriorValue:= To_Char(CData.C1); 
            end if;
          end if;
        end if;
      end loop;
      Dbms_Output.Put_Line('程序执行完毕,没有错误!');
    exception
      when eError then
        Null;
      when others then
        Dbms_Output.Put_Line('发现未知错误:' + SqlErrM);
    end;
    /
    执行结果
    exec PLogicChk(0);
    程序执行完毕,没有错误!
    exec PLogicChk(1);
    第4条数据错误,当前值是1,上一条是2, 2的后面只能是2,8