41.2. PL/Tcl 函数和参数
要用PL/Tcl语言创建一个函数,使用标准的CREATE FUNCTION语法:
CREATE FUNCTION _funcname_ (_argument-types_) RETURNS _return-type_ AS $$
# PL/Tcl function body
$$ LANGUAGE pltcl;
PL/TclU是一样的,除了语言应该声明为pltclu
之外。
函数体就是一段 Tcl 代码。当在一个查询里面调用这个函数,参数是作为变量 $1
... $``_n_
传递给 Tcl 脚本的。 结果是用通常的方法从 Tcl 代码中返回的,就是用一个return
语句。
比如,一个简单的返回两个整数值中较大值的函数可以这样定义:
CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS $$
if {$1 > $2} {return $1}
return $2
$$ LANGUAGE pltcl STRICT;
请注意STRICT
子句,它让我们可以不用考虑输入为 NULL 的情况: 如果传递了一个 NULL ,该函数实际上就不会被调用,而只是自动返回一个 NULL 结果。
如果是一个不严格的函数且一个参数的实际值是 NULL ,那么对应的$``_n_
变量将被设置为一个空字符串。要检测一个特定的参数是否为 NULL ,可以使用argisnull
函数。 比如,假设要求tcl_max
在一个参数为 null 而另外一个为非 null 时返回非 null 参数, 而不是 null :
CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS $$
if {[argisnull 1]} {
if {[argisnull 2]} { return_null }
return $2
}
if {[argisnull 2]} { return $1 }
if {$1 > $2} {return $1}
return $2
$$ LANGUAGE pltcl;
如上所述,要从 PL/Tcl 函数中返回一个 NULL 数值,可以执行return_null
。 不管函数是否严格,都可以这么做。
复合类型的参数是当做 Tcl 数组传递给函数的。数组中的元素名字就是复合类型里的属性名字。 如果在传递的行中某个属性为 NULL 数值,那它就不会在数组中出现。下面是一个例子:
CREATE TABLE employee (
name text,
salary integer,
age integer
);
CREATE FUNCTION overpaid(employee) RETURNS boolean AS $$
if {200000.0 < $1(salary)} {
return "t"
}
if {$1(age) < 30 && 100000.0 < $1(salary)} {
return "t"
}
return "f"
$$ LANGUAGE pltcl;
目前没有返回复合类型结果的支持。也不支持返回结果集。
PL/Tcl目前还不是完全支持域类型:它看待域类型和下层的标量类型是一样的。 这就意味着与域关联的约束将不会被强制。对于函数参数,这不是什么问题, 但是如果你把PL/Tcl函数声明为返回一个域类型,那么就有危险。