外部函数(external function)是使用C、C++、JAVA等语言编写,在数据库外编译并保存在DLL、so或jar等共享库文件,被数据库用户通过PL/SQL调用的函数。通过外部函数,数据库系统能够支持更多的接口实现,方便程序员实现更复杂的应用。本人最近工作接触了相关方面的知识,在这里跟大家分享一下。下面将主要针对ORACLE外部函数详细介绍使用方法。
ORACLE中使用外部函数需要创建一个共享库在数据库中的对象,运用CREATE LIBRARY创建共享库,DROP LIBRARY删除共享库。
(1)语法规则:
CREATE [OR REPLICE]
LIBRARY
[schema_name.]library_name
{IS|AS}
LANGAUGE C
‘share_library_file_name’;
Schema_name要创建的库所属的模式名;
library_name指明了别名库的名称,之后使用到该库时均使用该名称;
share_library_file_name使用的共享库的文件路径。
DROP LIBRARY [sch_name.]library_name;
Sch_name 库所在的模式名
library 要删除的库的名称。
CREATE OR REPLACE FUNCTION inner_name ( [ TYPE [, ...] ] )
RETURN TYPE
as
LANGUAGE C
library lib_name
name func_name;
parameters(para_name type,return type);
inner_name:函数名,lib_name: 共享库别名,func_name:C函数名,para_name:参数名
类型:支持C语言内置数据类型。
(2)使用步骤:
a) 修改配置文件
listener.ora文件中添加
(ADDRESS_LIST =(ADDRESS = (PROTOCOL = IPC)(KEY=EXTPROC)))
(ENVS = EXTPROC_DLLS=ANY)
tnsnames.ora文件中添加
(ADDRESS_LIST =(ADDRESS = (PROTOCOL = IPC)(KEY=EXTPROC)))
EXTPROC_CONNECTION_DATA=(DESCRIPTION =(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY=EXTPROC)))
(CONNECT_DATA =(SID = PLSExtProc)
(PRESENTATION = RO)))
b) 生成动态库(.so或.dll)
自定义函数OUT:
OUT(int a)
{
int b=0;
b=a*30;
return b;
}
c) 将动态库添加到oracle
使用create library添加动态库,oracle必需具有create library权限。
create or replace library TEST as 'D:\C-proj\test1\test.dll';
d) 创建外部函数
create or replace function outnum(num in binary_integer)
return binary_integer
as
language C
library TEST
name “OUT”;
parameters(num int,return int);
e) 调用外部函数
SQL>select outnum(20) from dual;
OUTNUM(20)
----------
600
(3)原理分析
外部函数功能的实现为开发人员提供了巨大的方便,开发人员只要根据数据库厂商的要求,写出特定功能的函数,就能成功将其运用于数据库存储过程中,进一步扩展应用功能。
为了保证功能的实现,首先要解决的问题是,如何让数据库识别用户定义的外部函数。对于这一点,ORACLE利用创建库和创建函数的功能将其映射到数据库中的一个具体对象,那么这就解决了识别的问题,也就是语法,语义分析阶段问题。这个阶段应该要保证参数和返回值 与实际外部函数的一致性。接下来就是如何正确执行的问题了,个人认为,既然是调用外部函数,肯定少不了动态加载共享库的过程,对于windows是dll,linux是so。加载指定的函数,一个重要的问题是按照外部函数实际定义的参数个数,参数类型以及参数顺序传递参数,否则外部函数无法正确解析参数值,导致参数与预期不一致,从而返回的结果也不正确,甚至导致进程断言等灾难性后果。所以ORACLE是不是在实现内部定义了很多函数模板,根据定义的函数类型,构造指定的函数模板,传递参数给外部函数,然后获取外部函数计算的返回值。但由于参数的个数,参数的类型,以及不同类型参数之间的相互顺序的多样性,可能导致模板种类可能会超级多,感觉不是这样实现的,但又想不出来怎么搞的?疑惑中......