第十五章 Caché 命令大全 KILL 命令
删除变量。
重点
KILL
会释放储存空间。- 独占
KILL
的使用。 - 声明的对象,不需要
CLOSE
,自动回收。 ZKILL
不会删除子节点。
大纲
KILL:pc killargument,...
K:pc killargument,...
其中 killargument 可以是
- variable,…
- (variable,…)
参数
pc - 可选-后置条件表达式
variable - 可选-变量名或以逗号分隔的变量名列表。不带括号:要删除的变量。带括号的:要保留的变量。
描述
KILL
命令有三种形式:
- 无参数
KILL
argumentless KILL
. KILL
变量列表inclusive KILL
.KILL
使用括号中的变量列表,称为exclusive KILL
.
不带参数的kill
命令将删除所有局部变量。它不会删除进程私有全局变量、全局变量或用户定义的特殊变量。
使用变量或逗号分隔的变量列表作为参数终止:
KILL variable,...
inclusive KILL
它只删除在参数中指定的变量。删除该变量在低于指定变量的所有级别上的所有下标的变量。变量可以是局部变量、进程私有变量或全局变量。它们不一定是实际定义的变量,但必须是有效的变量名。即使特殊变量的值是用户指定的,也不能删除该变量。尝试这样做会生成<SYNTAX>
错误。
使用括号中的变量或逗号分隔变量列表作为参数终止:
KILL (variable,...)
exclusive KILL
它删除除在参数中指定的变量之外的所有局部变量。指定的变量只能是局部变量。不能指定下标变量;指定局部变量将保留该变量及其所有下标。指定的局部变量不必是实际定义的变量,但它们必须是有效的局部变量名。
注意:KILL
可以删除由 Caché 对象创建的局部变量。因此,不要在任何可能影响系统结构(如%Save
中当前使用的%objTX
)或系统对象(如存储过程上下文对象)的上下文中使用无参数KILL
或EXCLUSIVE KILL
。在大多数编程环境中,应该避免这些形式的KILL
。
可以使用$DATA
函数来确定变量是已定义的还是未定义的,以及已定义的变量是否具有下标。KIll
变量会将其$DATA
状态更改为UNDEFINED
。
使用KILL
删除变量可以释放局部变量存储空间。 要确定或设置当前进程的最大存储空间(以千字节为单位),请使用$ZSTORAGE
特殊变量。要确定当前进程的可用存储空间(以字节为单位),请使用$STORAGE
特殊变量。
DHC-APP>w $STORAGE
268268904
参数
pc
可选的后置条件表达式。如果后置条件表达式为TRUE(计算结果为非零数值),则Caché执行KILL
命令。如果后置条件表达式为假(计算结果为零),则Caché不执行该命令。
variable
如果没有括在括号中:KILL
命令要删除的变量。变量可以是单个变量,也可以是逗号分隔的变量列表。
如果用括号括起来:kill
命令要保留的局部变量;kill
命令删除所有其他局部变量。变量可以是单个变量,也可以是逗号分隔的变量列表。
示例
在下面的示例中,inclusive KILL
删除局部变量a
、b
和d
,并删除进程私有全局^||ppglob
及其所有下标。其他变量不受影响:
/// d ##class(PHA.TEST.Command).TestKILL()
ClassMethod TestKILL()
{
SET ^||ppglob(1) = "fruit"
SET ^||ppglob(1, 1) = "apples"
SET ^||ppglob(1, 2) = "oranges"
SET a = 1, b = 2, c = 3, d = 4, e = 5
KILL a, b, d, ^||ppglob
WRITE "a=", $DATA(a), " b=", $DATA(b), " c=", $DATA(c), " d=",$DATA(d), " e=",$DATA(e),!
WRITE "^||ppglob(1)=", $DATA(^||ppglob(1)),
" ^||ppglob(1,1)=", $DATA(^||ppglob(1, 1)),
" ^||ppglob(1,2)=", $DATA(^||ppglob(1, 2))
}
DHC-APP>d ##class(PHA.TEST.Command).TestKILL()
a=0 b=0 c=1 d=0 e=1
^||ppglob(1)=0 ^||ppglob(1,1)=0 ^||ppglob(1,2)=0
在以下示例中,inclusive KILL
删除局部变量a(1)
及其下标a(1,1)、a(1,2)和a(1,1,1)
;它不删除局部变量a、a(2)或a(2,1)
:
/// d ##class(PHA.TEST.Command).TestKILL1()
ClassMethod TestKILL1()
{
SET a="food",a(1)="fruit",a(2)="vegetables"
SET a(1,1)="apple",a(1,1,1)="mackintosh",a(1,2)="banana"
SET a(2,1)="artichoke"
WRITE "before KILL:",!
WRITE $DATA(a)," ",$DATA(a(1))," ",$DATA(a(1,1))," ",$DATA(a(1,1,1))," ",
$DATA(a(2))," ",$DATA(a(2,1)),!
KILL a(1)
WRITE "after KILL:",!
WRITE $DATA(a)," ",$DATA(a(1))," ",$DATA(a(1,1))," ",$DATA(a(1,1,1))," ",
$DATA(a(2))," ",$DATA(a(2,1))
}
DHC-APP>d ##class(PHA.TEST.Command).TestKILL1()
before KILL:
11 11 11 1 11 1
after KILL:
11 0 0 0 11 1
在以下示例中,exclusive KILL
将删除除变量d
和e
之外的所有局部变量:
/// d ##class(PHA.TEST.Command).TestExclusiveKILL()
ClassMethod TestExclusiveKILL()
{
SET a=1,b=2,c=3,d=4,e=5
KILL (d,e)
WRITE "a=",$DATA(a)," b=",$DATA(b)," c=",$DATA(c)," d=",$DATA(d)," e=",$DATA(e)
}
DHC-APP>d ##class(PHA.TEST.Command).TestExclusiveKILL()
a=0 b=0 c=0 d=1 e=1
请注意,因为exclusive KILL
删除对象变量,所以上面的程序在终端会话中工作,但不在对象方法中工作。
下面的示例中, inclusive KILL
删除两个进程私有全局变量,而exclusive KILL
删除除变量d
和e
之外的所有局部变量。
/// d ##class(PHA.TEST.Command).TestKILLBoth()
ClassMethod TestKILLBoth()
{
SET ^||a="one",^||b="two",^||c="three"
SET a=1,b=2,c=3,d=4,e=5
KILL ^||a,^||c,(d,e)
WRITE "a=",$DATA(a)," b=",$DATA(b)," c=",$DATA(c)," d=",$DATA(d)," e=",$DATA(e),!
WRITE "^||a=",$DATA(^||a)," ^||b=",$DATA(^||b)," ^||c=",$DATA(^||c)
}
DHC-APP>d ##class(PHA.TEST.Command).TestKILLBoth()
a=0 b=0 c=0 d=1 e=1
^||a=0 ^||b=1 ^||c=0
注意
KILL
与 Objects
对象实例引用(OREF)自动维护引用计数-当前引用对象的项目数。无论何时将变量或对象属性设置为引用对象,Caché都会递增对象的引用计数。Kill
变量时,Caché会递减相应的对象引用计数。当此引用计数变为0时,对象会自动销毁;也就是说,Caché会将其从内存中删除。当变量设置为新值或变量超出作用域时,对象引用计数也会递减。
对于持久性对象,如果保留对该对象的更改,请在从内存中删除该对象之前调用%Save()
方法。%Delete()
方法删除Caché对象的存储版本;它不会删除该对象的内存版本。
在Caché5.0版之前,%Close()
方法可用于从内存中删除对象。在Caché版本5.0及更高版本中,%Close()
方法不执行任何操作,始终成功完成。编写新代码时不要使用%Close()
。
KILL 对象方法
可以在KILL
表达式的左侧指定对象方法。下面的示例指定%get()
方法:
SET obj=##class(test).%New() // 其中test是具有多维属性md的类
SET myarray=[(obj)]
SET index=0,subscript=2
SET myarray.%Get(index).md(subscript)="value"
WRITE $DATA(myarray.%Get(index).md(subscript)),!
KILL myarray.%Get(index).md(subscript)
WRITE $DATA(myarray.%Get(index).md(subscript))
Inclusive KILL
Inclusive KILL
只删除那些显式命名的变量。该列表可以包括局部变量、进程私有全局变量和全局变量(有下标或无下标)。Inclusive KILL
是删除全局变量的唯一方法。
可以使用KillRange()
方法删除一定范围的带下标的全局变量。
Exclusive KILL
Exclusive KILL
将删除除显式命名的变量之外的所有局部变量。列出的名称用逗号分隔。括号是必需的。
调用Exclusive KILL
时,不必定义例外列表中指定的局部变量。
例外列表只能包含本地无下标变量名。例如,如果有一个名为fruitbasket
的局部变量数组,它有几个下标节点,则可以通过指定kill(fruitbasket)
来保留整个局部变量数组;不能使用Exclusive KILL
来选择性地保留单个下标节点。
例外列表可以包含重新发送对象引用(OREF)的局部变量。例外列表不能包含对象引用的属性。
Exclusive KILL
列表不能指定进程私有全局变量、全局变量或特殊变量;尝试这样做会导致<SYNTAX>
错误。未在例外列表中命名的局部变量将被删除;后续对此类变量的引用会生成<unfined>
错误。Exclusive KILL
对进程私有全局变量、全局变量和特殊变量没有影响。但是,它删除了由系统对象创建的局部变量。
对数组使用KILL
可以使用包Inclusive KILL
删除整个数组或数组中的选定节点。指定的数组可以是局部变量、进程私有全局变量或全局变量。
- 要删除局部变量数组,请使用任何形式的
KILL
。 - 要删除局部变量数组中的选定节点,必须使用包
Inclusive KILL
。 - 要删除全局变量数组,必须使用
Inclusive KILL
。 - 要删除全局变量数组中的选定节点,必须使用
Inclusive KILL
。
要删除数组,只需将其名称提供给Inclusive KILL
即可。
例如,下面的命令删除全局数组^fruitbasket
及其所有从属节点。
/// d ##class(PHA.TEST.Command).TestKILLArray()
ClassMethod TestKILLArray()
{
SET ^fruitbasket(1)="fruit"
SET ^fruitbasket(1,1)="apples"
SET ^fruitbasket(1,2)="oranges"
WRITE "Before KILL:",!
WRITE "^fruitbasket(1)=",$DATA(^fruitbasket(1)),
" ^fruitbasket(1,1)=",$DATA(^fruitbasket(1,1)),
" ^fruitbasket(1,2)=",$DATA(^fruitbasket(1,1)),!
KILL ^fruitbasket
WRITE "After KILL:",!
WRITE "^fruitbasket(1)=",$DATA(^fruitbasket(1)),
" ^fruitbasket(1,1)=",$DATA(^fruitbasket(1,1)),
" ^fruitbasket(1,2)=",$DATA(^fruitbasket(1,1))
}
DHC-APP>d ##class(PHA.TEST.Command).TestKILLArray()
Before KILL:
^fruitbasket(1)=11 ^fruitbasket(1,1)=1 ^fruitbasket(1,2)=1
After KILL:
^fruitbasket(1)=0 ^fruitbasket(1,1)=0 ^fruitbasket(1,2)=0
要删除数组节点,请提供相应的下标。例如,下面的kill
命令删除下标1,2处的节点。
/// d ##class(PHA.TEST.Command).TestKILLArraySub()
ClassMethod TestKILLArraySub()
{
SET ^fruitbasket(1)="fruit"
SET ^fruitbasket(1,1)="apples"
SET ^fruitbasket(1,2)="oranges"
SET ^fruitbasket(1,2,1)="navel"
SET ^fruitbasket(1,2,2)="mandarin"
WRITE ^fruitbasket(1)," contains ",^fruitbasket(1,1),
" and ",^fruitbasket(1,2),!
WRITE ^fruitbasket(1,2)," contains ",^fruitbasket(1,2,1),
" and ",^fruitbasket(1,2,2),!
KILL ^fruitbasket(1,2)
WRITE "1st level node: ",$DATA(^fruitbasket(1)),!
WRITE "2nd level node: ",$DATA(^fruitbasket(1,1)),!
WRITE "Deleted 2nd level node: ",$DATA(^fruitbasket(1,2)),!
WRITE "3rd level node under deleted 2nd: ",$DATA(^fruitbasket(1,2,1)),!
QUIT
}
DHC-APP>d ##class(PHA.TEST.Command).TestKILLArraySub()
fruit contains apples and oranges
oranges contains navel and mandarin
1st level node: 11
2nd level node: 1
Deleted 2nd level node: 0
3rd level node under deleted 2nd: 0
删除数组节点时,会自动删除该节点的所有从属节点,以及仅包含指向已删除节点的指针的前一个节点。 如果删除的节点是其阵列中的唯一节点,则阵列本身将与该节点一起删除。
要删除多个局部变量数组,可以使用包含形式或排除形式的kill
,如上所述。例如,以下命令删除除array1
和array2
之外的所有本地数组。
KILL (array1,array2)
要删除多个数组节点,只能使用包含形式的KILL
。例如,下面的命令删除三个指定的节点,从每个数组中删除一个节点。
KILL array1(2,4),array2(3,2),array3(1,7)
节点可以在相同或不同的阵列中。
可以使用ZKILL
命令删除指定的本地或全局阵列节点。与KILL
不同,ZKILL
不会删除指定节点的所有从属节点。
使用参数传递的KILL
影响
通过参数传递,值将传递给用户定义的函数或使用do
命令调用的子例程。要传递给用户定义函数或子例程的值以逗号分隔的列表形式提供,称为实际参数列表。提供的每个值都按位置映射到为用户定义的函数或子例程定义的形参列表中的相应变量。
根据实际参数列表的指定方式,参数传递可以采用两种方式之一:按值传递或通过引用传递。
KILL
形参列表中的变量会产生不同的结果,具体取决于是按值传递还是按引用传递。
如果要按值传递变量,请执行以下操作:
- 在被调用的函数或子例程的上下文之外,
KIll
正式列表中的变量没有任何效果。这是因为在调用函数或子例程时,Caché会自动保存相应实际变量的当前值。然后,它会在退出函数或子例程时自动恢复保存的值。
在下面的按值传递示例中,Subrt1
中的kill
删除形式变量x
,但不影响实际变量a
:
/// d ##class(PHA.TEST.Command).TestKILLValue()
ClassMethod TestKILLValue()
{
Test
SET a=17
WRITE !,"Before Subrt1 a: ",$DATA(a)
DO Subrt1(a)
WRITE !,"After Subrt1 a: ",$DATA(a)
QUIT
Subrt1(x)
WRITE !,"pre-kill x: ",$DATA(x)
KILL x
WRITE !,"post-kill x: ",$DATA(x)
QUIT
}
DHC-APP>d ##class(PHA.TEST.Command).TestKILLValue()
Before Subrt1 a: 1
pre-kill x: 1
post-kill x: 0
After Subrt1 a: 1
如果通过引用传递变量:
-
执行
kill
并将变量包含在正式列表中也会KILL
相应的实际变量。当函数或子例程终止时,实际变量将不再存在。 -
执行
KILL
并排除形式列表中的变量会同时保留形式变量和通过引用传递的实际变量。
在下面的引用传递示例中,Subrt1
中的kill
删除形式变量x
和实际变量a
两者:
/// d ##class(PHA.TEST.Command).TestKILLRef()
ClassMethod TestKILLRef()
{
Test
SET a=17
WRITE !,"Before Subrt1 a: ",$DATA(a)
DO Subrt1(.a)
WRITE !,"After Subrt1 a: ",$DATA(a)
QUIT
Subrt1(&x)
WRITE !,"pre-kill x: ",$DATA(x)
KILL x
WRITE !,"post-kill x: ",$DATA(x)
QUIT
}
DHC-APP>d ##class(PHA.TEST.Command).TestKILLRef()
Before Subrt1 a: 1
pre-kill x: 1
post-kill x: 0
After Subrt1 a: 0
一般来说,不应该KILL形参列表中指定的变量。当Caché遇到使用参数传递(无论是通过值传递还是通过引用传递)的函数或子例程时,它会隐式地为形式列表中的每个变量执行一个new
命令。当它退出函数或子例程时,它会隐式地为形式列表中的每个变量执行kill
命令。在使用按引用传递的形式变量的情况下,它在执行KILL
之前更新相应的实际变量(以反映对形式变量所做的更改)。
事务处理
全局变量的KILL
被记录为当前事务的一部分;此全局变量删除在事务回滚期间被回滚。局部变量或进程私有全局变量的KILL不会记录在日志中,因此此变量删除不受事务回滚的影响。