第十九章 Caché 函数大全 $INCREMENT 函数
将指定的增量添加到变量的数值。
大纲
$INCREMENT(variable,num)
$I(variable,num)
参数
- variable 要增加其值的变量。它可以指定局部变量,进程专用全局变量或全局变量,并且可以带下标或不下标。该变量无需定义。如果未定义变量,或者将其设置为空字符串(
“”
),则$INCREMENT
将其视为具有零初始值,并相应地递增。此处不能指定文字值。不能将简单的对象属性引用指定为变量。可以使用语法obj.property
将多维属性引用指定为变量。 - num 可选-要添加到变量的数字增量。该值可以是数字(整数或非整数,正数或负数),包含数字的字符串或任何计算结果为数字的表达式。计算前导和尾随空白以及多个符号。计算字符串,直到遇到第一个非数字字符。空字符串(
“”
)的值为零。如果未为第二个参数指定num,则Caché默认将变量递增1。
描述
$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
SEQUENCE
$SEQUENCE
和$INCREMENT
可以用作替代方案,也可以彼此组合使用。 $SEQUENCE
专门用于涉及多个同时处理的整数增量运算。 $INCREMENT
是更通用的增量/减量函数。
-
$SEQUENCE
增加全局变量。$INCREMENT
递增局部变量,全局变量或过程专用全局变量。 -
$SEQUENCE
将整数增加1。$INCREMENT
将任何数值增加或减少任何指定的数值。 -
$SEQUENCE
可以为进程分配一定范围的增量。$INCREMENT
仅分配一个增量。 -
SET $SEQUENCE
可用于更改或取消定义(杀死)全局变量。$INCREMENT
不能在SET
命令的左侧使用。
$INCREMENT和全局变量
可以在全局变量或全局变量的下标节点上使用$INCREMENT
。可以使用扩展的全局引用访问映射到另一个名称空间的全局变量。可以使用裸全局引用访问下标的全局变量。
Caché按从左到右的顺序计算参数。如果num(要增加的数量)是下标的全局变量,则Caché使用此全局引用来设置裸指标,从而影响所有后续的裸全局引用。
递增字符串
$INCREMENT
通常用于递增包含数字值的变量。但是,它确实接受包含字符串的变量。在字符串上使用$INCREMENT
时,以下规则适用:
- 空字符串(
“”
)被视为值为零。 - 数字字符串(
“123”
或“+0012.30”
)被视为具有该数字值。该字符串将转换为规范形式:删除前导零和尾随零以及加号。 - 混合的数字/非数字字符串(“
12AB
”或“1,000
”)被视为直到第一个非数字字符的数值,然后在该点处被截断。 (请注意,逗号是一个非数字字符。)结果数字子串将转换为规范形式:删除前导零和尾随零以及加号。 - 非数字字符串(“
ABC
”或“$12
”)被视为值为零。 - 执行科学计数法转换。例如,如果
strvar =“3E2”
,则$INCREMENT
会将其视为具有300
的值。 - 不执行算术运算。例如,如果
strvar =“3 + 7”
,$INCREMENT
将截断加号处的字符串(将其作为非数字字符处理)并将strvar
递增为4
。 - 应避免在单个
$INCREMENT
语句中多次使用字符串变量。例如,避免将字符串变量连接到该变量的增量:strvar_$INCREMENT(strvar)
.这将返回不可预测的结果。
错误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
网友评论