• 自动行号功能实现不同方法研究


    

    方法一、

    只需要将序号定义成公式,并将公式设置为:get_block_property('block_name',current_record)就可以实现了,或者把这行语句放到“When-Create-Record”触发器中。

    缺点:增改删时,行号不能自动刷新。




    方法二、


    block的三个触发器中添加相应的代码:


    Key-Crerec:
    DECLARE
    LINE NUMBER;
    BEGIN
    LINE := :SYSTEM.CURSOR_RECORD;
    LOOP
    IF :SYSTEM.LAST_RECORD = 'TRUE' THEN 
    EXIT; 
    ELSE
    NEXT_RECORD; 
    :blk.ID := :SYSTEM.CURSOR_RECORD + 1; 
    END IF; 
    END LOOP;
    GO_RECORD(LINE);
    CREATE_RECORD;
    :blk.ID := :SYSTEM.CURSOR_RECORD;
    END;
    Key - Delrec:
    DECLARE
    LINE NUMBER;
    BEGIN
    DELETE_RECORD;
    LINE := :SYSTEM.CURSOR_RECORD;
    LOOP 
    :blk.ID := :SYSTEM.CURSOR_RECORD; 
    IF :SYSTEM.LAST_RECORD = 'TRUE' THEN 
    EXIT; 
    ELSE 
    NEXT_RECORD; 
    END IF; 
    END LOOP;
    GO_RECORD(LINE);
    END;
    When - Create - Record:
    :blk.ID := :SYSTEM.TRIGGER_RECORD;
    

    缺点:对于记录数很少的table适用,当table中的记录很多时,由于使用了循环操作,所以会影响效率。


     

    为了防止按F11时也生成序号,影响查询,可以在生成前加入以下条件:


    IF (:SYSTEM.MODE != ‘ENTER-QUERY’) THEN 


    方法三


    Step1创建3个参数和一个非数据库字段


    Parametername                                                 type       InitialValue


    P_BOLCKNAME_MAX_LINE_NUMBER    number


    P_BOLCKNAME_VALIDATE_FLAG            char


    P_BOLCKNAME_RESET_LINE_NUMBER  char        N


    在使用line_number功能的Block中添加一个非数据库Item


    Columnname                          type       InitialValue


    VAL_REC_FIRED_FLAG      char       N


     


    Step2block-leveltrigger中添加以下代码


    (1) pre_query


     BOLCKNAME.line_num('PRE-QUERY');


    (2) post_query


     BOLCKNAME.line_num('POST-QUERY');


    (3) when_create_record


     IF :PARAMETER. P_BOLCKNAME_RESET_LINE_NUMBER = 'Y' THEN


         copy('1',:PARAMETER.P_BOLCKNAME_MAX_LINE_NUMBER);


         :PARAMETER.P_BOLCKNAME_RESET_LINE_NUMBER:= 'N';


    END IF;


    BOLCKNAME.line_num('INIT');


    (4) when-validate-record


    BOLCKNAME.line_num('WHEN-VALIDATE-RECORD');


    (5) when-new-record-instance


    BOLCKNAME.line_num('WHEN-NEW-RECORD-INSTANCE');


    (6) on-clear-details(子块需添加,主块不需该trigger)


      IF :system.cursor_block = 'BOLCKNAME' andnvl(:system.coordination_operation,'X') in('CREATE_RECORD','NEXT_RECORD') 


    THEN


            copy('Y',P_BOLCKNAME_RESET_LINE_NUMBER);


       END IF;


    (7) pre_insert


     BOLCKNAME.catalog_group_line_unique; --行号唯一性的检查


    (8) pre_update


     BOLCKNAME.catalog_group_line_unique; --行号唯一性的检查


           


    VAL_REC_FIRED_FLAGItem leveltrigger中添加以下代码


    (1) WHEN-VALIDATE-ITEM


    BOLCKNAME.catalog_group_line_unique; --行号唯一性的检查


    BOLCKNAME.line_num('WHEN-VALIDATE-ITEM');


     


    Step3ProgrameUnit中添加名为BOLCKNAMEPACKAGE


    PACKAGE BLOCKNAME BODY中添加


      PROCEDURE line_num(event VARCHAR2) IS


                               x_max_line_num  NUMBER:= 0;


                               x_lines_curr_maxNUMBER;       


    BEGIN


                   IF(event = 'WHEN-VALIDATE-ITEM') THEN


                            --code 


        END IF ;


    END ;           


     


       PROCEDURE catalog_group_header_uniqueis


         l_rec_num number;


      BEGIN


            selectcount(1) into l_rec_num


          --code 


      END;


    具体代码参看附件:blockname_body.txt


     


    Step4在数据库中创建下面的PACKAGE


    红蓝两部分代码功能类似,区别在于蓝色代码多了一个line_type传入参数,可根据条件灵活调用。


    create or replace package bodyTVSN_CONTROL_F_PKG is


    PROCEDUREcheck_catalog_unique(p_catalog_header_idINNUMBER,


                                    P_catalog_LINE_ID  INNUMBER,


                                    P_catalog_LINE_NUM INNUMBER,


                                    p_validate_flag    OUTVARCHAR2) IS


                  p_record_numbernumber := 0;        


    BEGIN                               


    END;


    PROCEDUREget_catalog_max_num (P_catalog_header_idINNUMBER,


                                    P_MAX_NUM          OUTNUMBER) IS


    BEGIN


    END;


    PROCEDUREcheck_catalog_group_unique(p_catalog_group_header_idINNUMBER,


                                          p_catalog_line_type      INNUMBER,


                                          P_catalog_group_LINE_ID  INNUMBER,


                                          P_catalog_group_LINE_NUM INNUMBER,


                                          p_validate_flag          OUTVARCHAR2) IS


         p_record_number number :=0;                                      


    BEGIN


    END; 


    PROCEDUREget_catalog_group_max_num(P_catalog_group_header_idINNUMBER,


                                         p_line_type              INNUMBER,


                                         P_MAX_NUM           OUTNUMBER) IS


    BEGIN


    END;                                 


    endTVSN_CONTROL_F_PKg;


    注:此种方法有个缺陷,即可能产生断号的Line_Number,如现有行号为456的记录删除了行号为5的记录,那么新增一条记录的行号就为7,行号5就永远不可能被用到了。


     


    顺带介绍两个和行记录有关的API


    (1)   APP_RECORD.DELETE_ROW


    procedureAPP_RECORD.DELETE_ROW(


    check_delete BOOLEAN default FALSE, --是否检查Blockdelete_allowed属性


    product_name varchar2 default NULL,


    message_name varchar2 default NULL);


    functionAPP_RECORD.DELETE_ROW(


    check_delete BOOLEAN default FALSE,


    product_name varchar2 default NULL,


    message_name varchar2 default NULL)


    return BOOLEAN;


    API可应用删除记录时需提示时,确认后执行删除,取消则不删除,可以通过重写BlockKEY-DELREC Trigger添加APP_RECORD.DELETE_ROW;实现该功能。也可以利用下面的代码实现更复杂的删除逻辑。


    IF APP_RECORD.DELETE_ROW THEN


      Code1


    ELSE


      Code2


    END IF


     


    (2)   APP_RECORD. FOR_ALL_RECORDS


    API补充了本章开头介绍的Line_Number功能的断号缺陷,将两者结合起来应该是一种比较完善的解决方案,实现步骤如下:


    Step 1创建itemhandler procedures


    PACKAGE BODY lines IS


    line_number_seq number := 0;


    PROCEDURE delete_row IS


    BEGIN


    line_number_seq := 0;


    APP_RECORD.FOR_ALL_RECORDS(’reseq_line_number’);


    END delete_row;


    END lines;


     


    Step 2创建用户定义triggerRESEQ_LINE_NUMBER


    lines.line_number_seq := lines.line_number_seq + 1;


    :lines.line_number := lines.line_number_seq;


     


    Step 3KEY–DELETETrigger调用item handler procedures


    lines.line_number(’KEY–DELETE’); --删除记录时调用delete_row代码重置行号


     


    注意:当块中包含的记录数非常多时,那么重置行号将非常缓慢。如果块查询出的记录集只是所有记录的一部分,而行号又是主键字段,那么重置行号有可能导致主键重复的错误。如果在查询玩数据或保存提交后需要重置行号,那么可能需要修改record的状态将其标记为未修改。


    方法四


    在某些情况下,在新增、删除记录后,要求为 BLOCK中显示的 RECORD进行排序并


    且编号。完成这一动作可通过以下函数来完成:


    l APP_RECORD.FOR_ALL_RECORDS


    例子如下:


    LINES中有 ITEM: LINE_NUMBER。要求当记录被删除时, LINE_NUMBER要重


    新编号。


    步骤 1  创建 ITEM HANDLER


    PACKAGE BODY lines IS
    
    
    
    
    line_number_seq number := 0;
    
    
    
    
    PROCEDURE delete_row IS
    
    
    
    
    BEGIN
    
    
    
    
    line_number_seq := 0;
    
    
    
    
    APP_RECORD.FOR_ALL_RECORDS(’reseq_line_number’);
    
    
    
    
    END delete_row;
    
    
    
    
    END lines;
    


    步骤 2  创建自定义的TRIGGERRESEQ_LINE_NUMBER


    汉得信息技术有限公司 ORACLE应用开发培训手册


    Lesson 9 FORM中对象的编程 37


    Company  Confidential -For internal use only


    lines.lin e_number_seq :=lines.line_number_seq + 1;


    :lines.line_number :=lines.line_number_seq;


    步骤 3  调用 ITEM HANDLER


    Trigger: KEY– DELETE:


    lines.line_number(’KEY–DELETE’);


    方法五


    这个行号的特点是:


    1. 新增行时自动生成默认行号:已有的最大行号+1
    2. 用户可以修改行号为合法的数字:大于0;保证唯一
    3. 如果用户修改了行号,新增生成的行号必须在用户修改行号的基础上+1


    实现这样的行号相对比较麻烦,下面描述如何来实现上图中所示的行号功能:


    1. 在记录块的PRE-QUERY中查询出数据库中已有的最大行号,并将其记录到参数中作为最大的行号,如果单据的头是新建的,那这个参数默认的最大值则为1
    2. 在行记录的WHEN-CREATE-RECORD中将最大行号的参数值+1赋给行号字段
    3. 行号数据项的WHEN-VALIDATE-ITEM中检查行号是否<0;同时检查行号在数据库中是否存在(对于同时录入多行相同的行号在这个触发器中无需处理)
    4. WHEN-NEW-RECORD-INSTANCE中检查如果块的状态是NEW,从数据库中获取最大的行号,并设置行号
    5. WHEN-VALIDATE-RECORD中判断当前的行号是否大于参数中的最大行号,如果是则覆盖参数的最大行号


    procedure line_num ( event varchar2) is
      l_line_num_count number;
    begin	
      if ( event = 'WHEN-VALIDATE-ITEM') then
     
        if :lines.line_number <= 0 then
          fnd_message.set_name('XHU','XHU_ALL_ENTER_VALUE_GT_ZERO');
          fnd_message.error;
          raise form_trigger_failure;
        end if;
        -- check the unique line number from DB
        if xhu_orders_sv.po_line_num_exists(name_in('headers.header_id'),name_in('lines.line_number')) then
          fnd_message.set_name('XUH','XHU_ENTER_UNIQUE_LINE_NUM');
          fnd_message.error;
          raise form_trigger_failure;
        end if;
     
        elsif (event = 'WHEN-CREATE-RECORD') then
          :lines.line_number := :parameter.max_line_num + 1;
        elsif (event = 'PRE-QUERY') then
          -- get the maximums line number from the DB
          :parameter.max_line_num := xhu_orders_sv.get_max_line_num(name_in('headers.header_id'));
        elsif (event = 'WHEN-VALIDATE-RECORD') then
          if :lines.line_number > :parameter.max_line_num then
            :parameter.max_line_num := :lines.line_number ;
          end if;
        elsif (event = 'WHEN-NEW-RECORD-INSTANCE')then
        if upper(get_block_property('lines',status)) = upper('NEW')  and :System.Mode <> 'ENTER-QUERY' then
          :parameter.max_line_num := xhu_orders_sv.get_max_line_num(name_in('headers.header_id'));
          line_num('WHEN-CREATE-RECORD');
          SET_RECORD_PROPERTY(get_block_property('lines',current_record), 'lines', STATUS, NEW_STATUS );
        end if;
      else
          APP_EXCEPTION.INVALID_ARGUMENT('LINE_NUMBER', 'EVENT', EVENT);
      end if;
     
    exception
    	when others THEN
    	   	raise;
    end line_num;
     
    --headers:单据的头数据块
    --lines:行号所属的数据块
    --xhu_orders_sv.get_max_line_num:根据头ID取得数据库中单据的最大行号
    --XHU_ENTER_UNIQUE_LINE_NUM:消息字典:请输入唯一行号
    --XHU_ALL_ENTER_VALUE_GT_ZERO:消息字典:请输入大于0的值
    

    各触发器的HANDLER:

    procedure when_create_record is
    begin	
      lines.line_num('WHEN-CREATE-RECORD');	
    end when_create_record;
     
    procedure when_new_record_instance is
    begin
      lines.line_num('WHEN-NEW-RECORD-INSTANCE');
    end when_new_record_instance;
     
    procedure when_validate_record is
    begin	
      lines.line_num('WHEN-VALIDATE-RECORD');	
    end when_validate_record;
     
    procedure pre_query is
    begin
      lines.line_num('PRE-QUERY');
    end pre_query;
    
    添加一个MAX_LINE_NUM(NUMBER)的参数来保存当前最大行号的值



  • 相关阅读:
    微软老将Philip Su的离职信:回首12年职场生涯的心得和随笔[转]
    <Programming Ruby 1.9 The Pragmatic Programmer>读书笔记
    Ruby:Update value on specific row but keep the headers
    解决ImportError: cannot import name webdriver
    Ruby几个相关目录
    《发财日记》处处都是名言警句
    软件研发管理最佳实践(20121020 深圳)
    中国过程改进年会会前培训:让敏捷落地! 软件研发管理最佳实践(2012530 北京)
    展示你的才华,成就你的事业!—— 疯狂讲师
    网络直播课程 体验极限编程(XP)
  • 原文地址:https://www.cnblogs.com/wanghang/p/6299362.html
Copyright © 2020-2023  润新知