第十五章 Caché 命令大全 KILL 命令

第十五章 Caché 命令大全 KILL 命令

删除变量。

重点

  1. KILL 会释放储存空间。
  2. 独占KILL的使用。
  3. 声明的对象,不需要CLOSE,自动回收。
  4. 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)或系统对象(如存储过程上下文对象)的上下文中使用无参数KILLEXCLUSIVE 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删除局部变量abd,并删除进程私有全局^||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将删除除变量de之外的所有局部变量:

/// 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 删除除变量de之外的所有局部变量。

/// 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

注意

KILLObjects

对象实例引用(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,如上所述。例如,以下命令删除除array1array2之外的所有本地数组。

    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不会记录在日志中,因此此变量删除不受事务回滚的影响。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yaoxin521123

谢谢您的支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值