日期:2014-05-17  浏览次数:20883 次

请教下,这个逻辑怎么写好些?
需求是这样,现在有一张表, 我需要通过游标全部读取出来, 然后根据 第一个字段的值 分别做不同的操作,但是在做操作的时候,第一个字段必须按照一定的逻辑才能继续往下走 例子:
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在一起) 这样都是错误的数据
请问下这种情况如何判断才好呢? 谢谢

------解决方案--------------------
希望楼主满意!
SQL code
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('发现未知错误:' +