创建函数
CREATE FUNCTION 语句用于创建用户自定义函数。 其完整语法如下:
CREATE FUNCTION name "(" { arg_name data_type [ "," ... ] ")"
RETURNS return_type [VOLATILE]
AS library_path ["," c_function_name ] |
IN "'"language_name"'" AS "'"function_body"'"
data_type:
BIT | BOOLEAN | CHAR [ "(" size ")" ] | VARCHAR [ "(" size ")" ] | LOGNVARCHAR [ "(" size ")" ] |
STRING [ (" width ")" ] | UNICODE[ (" width ")" ] -- corresponds to SmartEDB nstring or nchar
| TINYINT -- signed<1>
| SMALLINT -- signed<2>
| INT [ "(" n ")" ] -- where n=1,2,4,8 corresponds to SmartEDB signed<n>
| INTEGER [ "(" n ")" ] -- where n=1,2,4,8 corresponds to SmartEDB signed<n>
| UNSIGNED [ "(" n ")" ] -- where n=1,2,4,8 corresponds to SmartEDB unsigned<n>
| BIGINT -- signed<8>
| FLOAT
| REAL -- double
| DOUBLE
| NUMERIC [ "(" width [ "," precision ] ")" ] -- SmartEDB numeric< width,precision> type
| DECIMAL [ "(" width [ "," precision ] ")" ] -- SmartEDB numeric< width,precision> type
| DATE -- SmartEDB 8-byte datetime type
| TIME -- SmartEDB 8-byte datetime type
| TIMESTAMP -- SmartEDB 8-byte datetime type
| BIANRY [ "(" size ")" ] --- array or vector of signed<1>
| VARBINARY [ "(" size ")" ] --- array or vector of signed<1>
| LONGVARBINARY [ "(" size ")" ] --- array or vector of signed<1>
| REFERENCE
| BLOB
| ARRAY "(" data_type [ "," length ] ")"
| SEQUENCE "(" scalar_data_type [ ASC | DESC ] ")"
| user-defined-type -- declared by "create domain"
请注意,在 SmartESQL 中,所有 SQL 关键字均不区分大小写,即“CREATE FUNCTION”和“create function”是等效的。
示例
例如,可以执行以下 SQL 语句,将 C++ 用户定义函数 load_cme_trades() 加载为 SQL 函数 load_trades() :
create function load_trades(fname string, book string) returns integer as 'mcocme', 'load_cme_trades';
这里,mcocme 指的是动态加载文件 libmcocme.so(在 Windows 系统上为 mcocme.dll),其中包含用户自定义函数 load_cme_trades 的实现。
执行此语句时,如果表“Functions”尚未创建,则会创建该表,并插入定义此用户定义函数(UDF)的行。
若要创建可在脚本语言中定义的函数,该函数可作为存储过程被调用,则可以使用 create 语句的第二种形式。例如,Lua 用户定义函数(UDF)可以定义如下:
create function twice(x integer) returns integer in 'lua' as 'return x+x end';
或者,可以将 Python 用户自定义函数(UDF)定义如下:
create function pyadd(x int, y int) returns int in 'python' as 'return x+y end';
然后,可以在 SQL 中使用如下语句执行这些用户定义函数(UDF):
XSQL>select twice(3), pyadd(5,7);
#1 #2
-----------------------------------------
6 12
Selected records: 1
当首次调用 Python 用户定义函数(UDF)时,它会加载 Python 解释器,编译函数代码并执行。在内存中保存对创建的解释器对象和编译代码的引用,因此在应用程序的生命周期内,此加载过程仅发生一次,并且 UDF 也仅编译一次。
(请注意,对于 Windows 用户,Python UDF 模块(DLL)mcopythonapi.dll 是 SmartESQL 引擎的插件模块,并且与库 mcosql.dll 存在链接依赖关系。这意味着,若要从用户程序使用 UDF(包括 Lua 以及 Python UDF),则必须动态加载 SmartESQL 和 SmartEDB 核心运行时。有关详细信息,请参阅 mco_core_load())
函数缓存
当执行函数调用时,SQL 引擎会存储函数结果,并在后续对该函数的调用中使用此缓存值,前提是函数参数相同;即在查询中参数是相同的语法结构。
所以,如果满足以下条件,调用将被缓存:
- 该参数是一个常量表达式或者
- 该参数在物理上是相同的数据库值;即它是同一表中同一行的同一列值。
如果出现以下情况,则不会被缓存:
- 查询中出现了一个常量表达式或列,且出现次数超过一次。
实际上,已知只有两种用例会使用函数结果缓存:
- 在执行类似“select * from A,B where sin(A.x) > 0;”这样的查询时,对两个表 A 和 B 进行连接操作,对于结果中的多行,对常量表达式 sin(A.x) 进行求值。这里函数 sin(A.x) 只会被调用 cardinality(A) 次,而不是 cardinality(A) * cardinality(B) 次。对于某些函数,这种缓存方式并不合适,例如 random() 函数。若要为特定函数禁用缓存,可以使用 VOLATILE 标志。
示例
create function vmtf(name varchar, dept_no unsigned(2), salary unsigned(4)) returns int VOLATILE in 'lua' as '
require("test_udf")
return mtf_impl(name, dept_no, salary)
end
';
- 要删除一个函数,需使用“drop function”语句。