第十九章 Caché 函数大全 $INCREMENT 函数

2020-09-09  本文已影响0人  Cache技术分享

第十九章 Caché 函数大全 $INCREMENT 函数

将指定的增量添加到变量的数值。

大纲

$INCREMENT(variable,num)
$I(variable,num)

参数

描述

$INCREMENT通过将指定的增量添加到变量的现有值并返回递增的值来重置变量的值。在以下示例中显示:

/// d ##class(PHA.TEST.Function).INCREMENT()
ClassMethod INCREMENT()
{
    SET a=7
    SET result=$INCREMENT(a)
    WRITE !,result   /* 结果是8 (a+1)  */
    WRITE !,a        /* 变量a现在也是8 */
}
DHC-APP>d ##class(PHA.TEST.Function).INCREMENT()
 
8
8

可以使用$GET函数返回变量的当前值。

$INCREMENT作为原子操作执行此增量,不需要使用LOCK命令。

如果多个进程通过$INCREMENT同时增加同一全局变量,则每个进程都会收到一个唯一的,递增的数字(如果num为负,则减小的数字)。在某些情况下,某些数字可能由于计时问题而被跳过。

如果$INCREMENT在回滚的事务中,则Caché不会恢复原始的非增量值。

$INCREMENT$ZINCREMENT具有相同的语法和效果。可以在任何使用$ INCREMENT的情况下使用$ZINCREMENT

参数

variable

要增加其数据值的变量。它必须是变量,不能是文字。不需要定义变量。 $INCREMENT定义一个未定义的变量,将其值设置为num(默认为1)。

变量参数可以是局部变量,进程专用全局变量或带下标或未下标的全局变量。如果是全局变量,则可以包含扩展的全局引用。如果是下标的全局变量,则可以使用裸露的全局引用来指定它。

可变参数可以是多维属性参考。例如,

$INCREMENT(..Count)。它不能是非多维对象属性。尝试递增非多维对象属性会导致<OBJECT DISPATCH>错误。

$INCREMENT不能递增特殊变量,即使是可以使用SET修改的变量也不能递增。尝试递增特殊变量会导致<SYNTAX>错误。

num

要增加(或减少)的数量。 num参数可以是正数(递增变量的值),也可以是负数(递减变量的值)。它可以是整数或小数。 num可以为零(无增量)。数字字符串被视为数字。空字符串(“”)或非数字字符串将被视为零增量。如果未指定增量,则Caché将使用默认增量一(1)。

DHC-APP>w $i(a,0)
8
DHC-APP>w $i(a,1)
9
DHC-APP>w $i(a,-1)
8

INCREMENT或SEQUENCE

$SEQUENCE$INCREMENT可以用作替代方案,也可以彼此组合使用。 $SEQUENCE专门用于涉及多个同时处理的整数增量运算。 $INCREMENT是更通用的增量/减量函数。

$INCREMENT和全局变量

可以在全局变量或全局变量的下标节点上使用$INCREMENT。可以使用扩展的全局引用访问映射到另一个名称空间的全局变量。可以使用裸全局引用访问下标的全局变量。

Caché按从左到右的顺序计算参数。如果num(要增加的数量)是下标的全局变量,则Caché使用此全局引用来设置裸指标,从而影响所有后续的裸全局引用。

递增字符串

$INCREMENT通常用于递增包含数字值的变量。但是,它确实接受包含字符串的变量。在字符串上使用$INCREMENT时,以下规则适用:

错误Increment

如果$INCREMENT无法递增变量,则会发出<MAXINCREMENT>错误。仅当num增量值非常小和/或变量值非常大时才会发生这种情况。

零(num = 0)递增总是返回原始数字,而不管其大小如何。它不会发出错误。

<MAXINCREMENT>发生在参数的数值类型不同并且所产生的类型转换和舍入不会导致递增时。如果对一个非常大的数字使用$INCREMENT,则默认增量1(或num的某个其他较小的正值或负值)太小而不明显。同样,如果指定一个非常小的小数数值,它的值也会太小而没有意义。$INCREMENT不是返回原始变量数而不递增,而是生成一个<MAXINCREMENT>错误。

在下面的示例中,1.2E18是可以递增或递减1的数字。 1.2E20是一个太大的数字,无法递增或递减1。前三个$INCREMENT函数成功递增或递减数字1.2E18。第四和第五个$INCREMENT函数以零递增,因此无论原始数字的大小如何,始终返回原始数字不变。第六和第七个$INCREMENT函数提供了一个足够大的num增量,可以成功地递增或递减数字1.2E20。第八个$INCREMENT函数试图将1.2E20加1,从而产生一个<MAXINCREMENT>错误。

/// d ##class(PHA.TEST.Function).INCREMENT1()
ClassMethod INCREMENT1()
{
    SET x=1.2E18
    WRITE "E18      :",x,!
    WRITE "E18+1    :",$INCREMENT(x),!
    WRITE "E18+4    :",$INCREMENT(x,4),!
    WRITE "E18-6    :",$INCREMENT(x,-6),!
    WRITE "E18+0    :",$INCREMENT(x,0),!
    SET y=1.2E20
    WRITE "E20      :",y,!
    WRITE "E20+0    :",$INCREMENT(y,0),!
    WRITE "E20-10000:",$INCREMENT(y,-10000),!
    WRITE "E20+10000:",$INCREMENT(y,10000),!
    WRITE "E20+1    :",$INCREMENT(y),!
}

DHC-APP>d ##class(PHA.TEST.Function).INCREMENT1()
E18      :1200000000000000000
E18+1    :1200000000000000001
E18+4    :1200000000000000005
E18-6    :1199999999999999999
E18+0    :1199999999999999999
E20      :120000000000000000000
E20+0    :120000000000000000000
E20-10000:119999999999999990000
E20+10000:120000000000000000000
E20+1    :
 WRITE "E20+1    :",$INCREMENT(y),! }
                    ^
<MAXINCREMENT>zINCREMENT1+12^PHA.TEST.Function.1

锁定和同时全局增量

$INCREMENT$ZINCREMENT当它们递增变量时不执行锁定操作,也不对变量使用LOCK命令会阻止$INCREMENT递增或递减其值。例如,假设进程1对^COUNTER执行锁定:

LOCK ^COUNTER

然后假设,过程2递增^COUNTER

SET x=$INCREMENT(^COUNTER,VAL)

进程1持有的锁不会阻止进程2递增^COUNTER

除非两个进程都使用$INCREMENT,否则不能保证这两个进程具有自己唯一的^COUNTER值。

$INCREMENT和事务处理

$INCREMENT的常见用法是在向数据库添加新条目之前增加计数器。 $INCREMENT提供了一种非常快速地执行此操作的方法,从而避免了使用LOCK命令。

这样做的代价是计数器未锁定。计数器可以在事务中由一个进程递增,而在该事务仍在处理时,可以在并行事务中由另一个进程递增。

如果必须回滚任何一个事务(或任何其他使用$INCREMENT的事务)(使用TROLLBACK命令),则计数器增量将被忽略。计数器变量不会减少,因为尚不清楚结果计数器值是否有效。这样的回滚极有可能对其他交易造成灾难性的影响。

示例

以下示例将myvar的值增加n。请注意,myvar不必是事先定义的变量:

/// d ##class(PHA.TEST.Function).INCREMENT2()
ClassMethod INCREMENT2()
{
    SET n=4
    KILL myvar
    SET VAL=$INCREMENT(myvar,n)       ; returns 4
    WRITE !,myvar
    SET VAL=$INCREMENT(myvar,n)       ; returns 8
    WRITE !,myvar
    SET VAL=$INCREMENT(myvar,n)       ; returns 12
    WRITE !,myvar
}
DHC-APP 2d1>d ##class(PHA.TEST.Function).INCREMENT2()
 
4
8
12

以下示例使用$INCREMENT将增量值添加到进程专用全局变量^|| xyz$INCREMENT的单参数形式加1;两个参数的形式以第二个参数中指定的值递增。在这种情况下,第二个参数是一个非整数值。

/// d ##class(PHA.TEST.Function).INCREMENT3()
ClassMethod INCREMENT3()
{
    KILL ^||xyz
    WRITE !,$INCREMENT(^||xyz)       ; returns 1
    WRITE !,$INCREMENT(^||xyz)       ; returns 2
    WRITE !,$INCREMENT(^||xyz)       ; returns 3
    WRITE !,$INCREMENT(^||xyz,3.14)  ; returns 6.14
}

DHC-APP>d ##class(PHA.TEST.Function).INCREMENT3()
 
1
2
3
6.14

以下示例显示了增加零(0)和增加负数的效果:

/// d ##class(PHA.TEST.Function).INCREMENT4()
ClassMethod INCREMENT4()
{
    KILL xyz
    WRITE !,$INCREMENT(xyz,0)  ; initialized as zero
    WRITE !,$INCREMENT(xyz,0)  ; still zero
    WRITE !,$INCREMENT(xyz)    ; increments by 1 (default)
    WRITE !,$INCREMENT(xyz)    ; increments by 1 (=2)
    WRITE !,$INCREMENT(xyz,-1) ; decrements by -1 (=1)
    WRITE !,$INCREMENT(xyz,-1) ; decrements by -1 (=0)
    WRITE !,$INCREMENT(xyz,-1) ; decrements by -1 (=-1)
}
DHC-APP>d ##class(PHA.TEST.Function).INCREMENT4()
 
0
0
1
2
1
0
-1

下面的示例显示使用混合(数字和非数字)num字符串和空字符串进行递增的效果:

/// d ##class(PHA.TEST.Function).INCREMENT5()
ClassMethod INCREMENT5()
{
    KILL xyz
    WRITE !,$INCREMENT(xyz,"")
           ; null string initializes to 0
    WRITE !,$INCREMENT(xyz,2)
           ; increments by 2
    WRITE !,$INCREMENT(xyz,"")
           ; null string increments by 0 (xyz=2)
    WRITE !,$INCREMENT(xyz,"3A4") 
           ; increments by 3 (rest of string ignored)
    WRITE !,$INCREMENT(xyz,"A4")
           ; nonnumeric string evaluates as zero (xyz=5)
    WRITE !,$INCREMENT(xyz,"1E2")
           ; increments by 100 (scientific notation)
}
DHC-APP>d ##class(PHA.TEST.Function).INCREMENT5()
 
0
2
2
5
5
105
上一篇下一篇

猜你喜欢

热点阅读