SNRO:Number Range

时间:2023-08-17 22:48:50

业务对象是在一定的编号范围内分配编号的,编号既可以是内部分配也可以是外部分配。对于外部分配,用户输入编号,系统检查这个编号是否被占用。对于内部分配,系统会自动的把编号分配给业务对象。所以内部分配和外部分配有不同的Number range。对于编号的分配,要考虑法规要求和业务规则,比如要求编号必须是连续的,按发生时间顺序排列等。为了保证编号的分配没有问题,可以通过相应的number range object来实现。

个字符。如果维护了number range transaction字段,可以通过这个T-CODE来维护该Number range。在warning field必须维护0.1到99.9之间的数值。系统会自动建议buffering value,除非特殊的情况才取消buffer设置。

Number range的intervals可以是数字,也可以是字母(只适用于external)。Number range number用来标识一个number range,可以是数字也可以是字母。当number range是通过fiscal year来组织的时候,一个number range可以有多个interval。

Internal number assignment中通过function module:NUMBER_GET_NEXT来得到下一个可用的number。当通过improt parameter来指定取得number的个数时,export parameter就会返回取得的number的个数,被分配的numbers就位于number – export-quantity + 1到number。如果interval的最后一个Number已经被分配,如果在number range object定义中roll flag被激活,number assignment又会从第一个number开始。Function module的return code说明了number assignment的情况:

l         0 number assignment successfully

l         1 number assignment successfully,but many numbers are still available in critical area

l         2 number assignment successfully , but the last number is assigned to you

l         3 you request more numbers than you request. The assigned numbers are assigned to you

CALL FUNCTION 'NUMBER_GET_NEXT'

   EXPORTING

       Nr_range_nr   = <number_range_number>

       Object        = <number_range_object_name>

       Quantity      = <quantity_of_numbers>

       Subobject     = <number_range_sub_object_name>

       Toyear        = <to_fiscal_year>

       Ingnor_buffer = <ignore_buffer_flag>

   IMPORTING

       Number        = <next_free_number>

       Quantity      = <quantity_of_numbers_to_read>

       Return_code   = <return_code>

   EXCEPTIONS

       Internal_not_found = 1

       Number_range_not_intern = 2

       Object_not_found = 3

       Internal_overflow = 4.

 
 

对于external number assignment通过function module NUMBER_CHECK来检查分配的number是否在number interval中。Export parameter returncode返回检查的结果,space,number在number range interval中,X,number在number range interval之外。

    CALL FUNCTION 'NUMBER_CHECK'

       EXPROTING

           Nr_range_nr       = <number_range_number>

           Number            = <number_to_be_checked>

           Object            = <number_range_object_name>

           Subobject         = <number_range_sub_object_name>

           Toyear            = <to_fiscal_year>

       IMPORTING

           Returncode        = <return_code>

       EXCEPTIONS

           Internal_not_found = 1

           Number_range_not_extern = 2

           Object_not_founr =3.

通过function module 'NUMBER_GET_INFO'可以得到number range object的某个interval信息,信息通过interval parameter传递,interval的structure type为NRIV。

    Number range存在表NRIV中,表中每条记录代表一个number range,如果number range object没有被缓存,每次读取新的number时,都需要直接访问这个数据库表,相应的记录也会在当前的LUW中被lock。优点是,number是连续的没有间隔,而且number是按照发生的先后顺序分配的缺点是,由于database lock需要顺序执行,增加系统负载,当过个请求指向同一个number range object时,会导致较长的系统等待时间。

    可以通过buffer number range来大大提高系统性能,buffer将number assignment的负载转给了application server。当buffer中的numbers被分配完毕,就会重新填充新的number packet,在number range object定义中指定放在缓冲中number的数量。通过这种机制,只有当buffer中的number被分配完后才会去访问数据库表。这就大大提高了性能,这也是为什么在法规和业务允许的情况下必须使用number range的原因。Function module NUMBE_GET_NEXT允许你通过参数来ignore buffer。Number range server是application server上的logical units,有自己的luw,所以在出现网络错误,number assignment难面会出间隔。另外一层意思是每个application server都是一块一块的从database取numbers。Serialization只发生在每个server层面。如果所有的number都被分配,就没有gap但是也不是按照时间发生的先后顺序来分配的。

个function group用来管理number range object:

FUNCTION GROUP

DESCRIPTION

SNR0

Maintenance dialog for number ranges, intervals and groups

SNR1

Service for maintaining and reading number range intervals and groups

SNR2

Service for reading, maintaining and for  maint. Dialog with no. range objects

SNR3

Number checks and assignments

SNR4

Utilites

通常情况下,SNR3中的function module就可以实现number range object的所有标准功能。可以通过SM56来维护number range buffer。

0

 
 

From <http://scnblogs.techweb.com.cn/abaplv/archives/179.html>

 
 

 
 

关于abap实现主键自增

2014年4月7日

0:31

 
 

 you don't have to create a module. You don't have to modify screen! For this purpose you need you have event. When you modify screen and regenerate maintence view you will lost all your changes!

 
 

So, I will try to do step by step manual for you (this manual is for 2 screens maintenance view only):

 
 

1. open tcode SE11

2. write down table name and press change button

3. Go to menu Utilities ->Table maintenance generator

4. Go to menu Environment -> Modification -> Events

5. Click new entries button

6. in the first column write 05 (creating new entry)

7. in 2nd column write down form name, e.g. autoincrement

8. now press button in 3rd column (you will go to the abap editor - here you have to choose include into which you want to put your code)

9. in the form you have to assign value to your field REC_INCREMENT. Now is up to you how you will hold the value for autoincrement field (I mean you have more possibilities how to do it - one is that you find out max value in the table ZTQM_VBATCH_COPY but the best one is to use tcode SNRO to create your own range - here you have to create an object and specify values range. Then in the code you automatically get next number by call of function module NUMBER_GET_NEXT

10. So go to tcode SNRO and create your object (e.g. zauto) and specify range values e.g. 1 - 1 000 000

11. implement following code

 
 

FORM autoincrement.
DATA: l_num TYPE CMS_DTE_SEQNO.
CALL FUNCTION 'NUMBER_GET_NEXT'
EXPORTING
nr_range_nr = '01'
object = 'ZAUTO'
IMPORTING
number = l_num
EXCEPTIONS
interval_not_found = 1
number_range_not_intern = 2
object_not_found = 3
quantity_is_0 = 4
quantity_is_not_1 = 5
interval_overflow = 6
buffer_overflow = 7
OTHERS = 8.

ZTQM_VBATCH_COPY-REC_INCREMENT = l_num.
ENDFORM.

 
 

That's all. This form will automatically fill table field REC_INCREMENT. It will work as follows:

 
 

you open SM30, specify table name and go to edit mode. Push the button new entries and you will automatically go to the second screen. There you fill your fields and then press back or save button, your autoincrement will be automatically filled.

 
 

Regards,

 
 

  Karol

 
 

From <http://scn.sap.com/message/7474131>

 
 

 
 

Navigate

2014年6月5日

18:39

 
 

1.注意获取号码的时候也是需要加锁的

 
 

2.这种方式适合获取一个号码

良信的一下子打印几千个的方式需要考虑是否合适

 
 

1.sap numbe range在标准程序中使用

之前一直不明白会计凭证编号sap是怎么做到连续编号,还以为是简单的做个全局变量,虽然形式差不多,但是sap有专门的TCODE和方法,可以保证号码不重复且可以做到只在某一个区间。甚至每年都会重新编号,像会计凭证编号,当达到某一程度的时候还会提醒。

2.如何自己创建

TCODE:SNRO。可以自己创建。如图:

SNRO:Number Range

短文本和长文本用来说明这个编号范围对象,输入任意描述即可。 

 
 

子对象数据元素我们这里不填。这里需要说明一下,所谓子对象,多数指一个组织结构,比如公司代码、销售组织、工厂等,这样编号就在对应的每个组织下面独立编号,最典型的例子是财务凭证,每个公司代码下的财务凭证都是独立编号的(其对应的数据表 BKPF,也必定把公司代码做为一个键字段)。而我们这个调度单对应于销售订单,销售订单没有按照组织级别分别编号,因此相应的调度单也就不需要了。

 
 

到期年标记是指编号按年度归零,每当开始一个新年度时,相应的编号也需要从头开始,比如财务凭证和物料凭证都是这样(比如表BKPF 和MKPF,都把年度做为一个键字段)
,而我们的调度单不需要对应年度,因此这里也不打勾。

,因此这个编号范围对象生成的编号长度也是 10 位。

无翻滚间隔是指如果编号达到最大,是否自动从头开始,勾上就不从头开始,而在获取编号的时候提示出错。我们这里应该打勾。

 
 

编号范围处理,属于翻译问题,实际就是编号范围的事务码,如果指定这个事务码,就可以不需要通过 SNUM 或者 SNRO 的主屏幕然后输入编号范围对象的名字来维护这个编号范围,而可以输入事务码直接进入它的号码范围维护屏幕。

 
 

,就是95%的时候提示。

  
 

主内存缓冲是指系统为了提高性能而预先取出一些编号放在应用服务器上,当程序取用编号时直接从应用服务器获取,而无需再读取数据库了。通常,如果对号码的连续性要求不高的情况下可以使用这种方式,而如果是财务凭证等要求连续的编号,则应该把主内存缓冲关闭,方法是通过菜单"编辑-设置缓存-无缓存"。

接着就可以在如图:

SNRO:Number Range

间隔中添加编号范围。

3.程序中如何使用

程序中我们也可以使用number range。使用三个函数即可。下面做以说明。

CALL FUNCTION 'NUMBER_RANGE_ENQUEUE

       EXPORTING 

            object           = 'ZSDDNR' 

       EXCEPTIONS 

            foreign_lock     = 1 

            object_not_found = 2 

            system_failure   = 3 

            OTHERS           = 4. 

*  **如果号码范围存在 

  if sy-subrc eq 0 . 

*  ****得到一个号码, 

      CALL FUNCTION 'NUMBER_GET_NEXT

           EXPORTING 

                nr_range_nr             = '01' 

                object                  = 'ZSDDNR' 

           IMPORTING 

                number                  = L_SEQNO 

*   quantity = quant 

*   returncode = code 

           EXCEPTIONS 

                interval_not_found      = 1 

                number_range_not_intern = 2 

                object_not_found        = 3 

                quantity_is_0           = 4 

                quantity_is_not_1       = 5 

                interval_overflow       = 6 

                buffer_overflow         = 7 

                OTHERS                  = 8. 

*  ***将号码累加 

      CALL FUNCTION 'NUMBER_RANGE_DEQUEUE

           EXPORTING 

                object           = 'ZSDDNR' 

           EXCEPTIONS 

                object_not_found = 1 

                OTHERS           = 2. 

  else . 

    raise NUM_RANGE_ERROR . 

  endif .

很容易理解,首先判断是否有这个number range,如果存在的话,就获得下个序号,最后一个函数我估计意思是释放这个全局变量的内存。'ZSDDNR'就是我们创建的number range。如此就可以像会计凭证编号那样每次都可以自动生成流水号了!流水号可以在自建表中用作主键,它的产生就靠上面的函数。

 
 

From <http://blog.csdn.net/donkey2004112103/article/details/4070996>

 
 

号码生成

2014年12月15日

10:50

 
 

  1. 简单的可以考虑sap的号段

    SNRO

  2. 考虑使用单例模式

    全局的class 静态属性保存当前序列号

    配合lock功能 按需设计一个号码生成器

     
     

    (对于号码本省,可以考虑增加"批" "累计打印"等属性

    同时设计一张统计信息表,方便后续出报表

    另外在实际业务中,需要考虑事务性的提交

    以及打印失败,号码delete之类的需求)

     
     

  3. SNRO本来是client独立的

    但是也提供了transport的功能

     
     

    这个transport会把当前的状态传递到目标client

    所以传输的时候 一定要注意在目标client的重置号码段

     
     

    或者号码段不通过传输实现

    在各个client独立配置 这也是sap recommend的操作方式

 
 

     constructor.

  private section.

 
 

    class-data:

      g_no type i,

      go_generator type ref to cl_no_generator.

 
 

 
 

endclass.

 
 

 
 

class cl_no_generator implementation.

  method get_instance.

    get_lock( exceptions foreign_lock = 1 others = 2 ).

    if sy-subrc <> 0.

      raise foreign_lock.

    endif.

 
 

    if go_generator is initial.

      create object go_generator.

    endif.

 
 

    eo_generator = go_generator.

  endmethod.

 
 

 
 

  method get_lock.

    write:/ 'Mock get lock' .

  endmethod.

 
 

 
 

  method release_lock.

    write:/ 'Mock release lock'.

  endmethod.

 
 

  method build.

    g_no = g_no + i_count.

    write:/'Mock generater:',i_count.

    write:/'Current no:',g_no.

 
 

  endmethod.

 
 

  method constructor.

    data:

      lt_stack type SYS_CALLST,

      ls_stack like line of lt_stack.

    CALL FUNCTION 'SYSTEM_CALLSTACK'

*     EXPORTING

*       MAX_LEVEL          = 0

     IMPORTING

*       CALLSTACK          =

       ET_CALLSTACK       = lt_stack

              .

 
 

    read table lt_stack into ls_stack index 2.

    if ls_stack-eventname <> 'GET_INSTANCE'.

      message '不允许直接创建实例' type 'E'.

    endif.

 
 

  endmethod.

endclass.

 
 

 
 

start-of-selection.

data: lo_generator type ref to cl_no_generator.

 
 

*create object lo_generator.

 
 

  call method  cl_no_generator=>get_instance

    importing eo_generator  = lo_generator

    exceptions foreign_lock = 1.

 
 

  if sy-subrc <> 0.

 
 

  endif.

 
 

  lo_generator->build( i_release = '' ).

  lo_generator->build( exporting i_count = 2 i_release = '' ).

  lo_generator->build( exporting i_count = 3 ).