外部函数

     外部函数(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是不是在实现内部定义了很多函数模板,根据定义的函数类型,构造指定的函数模板,传递参数给外部函数,然后获取外部函数计算的返回值。但由于参数的个数,参数的类型,以及不同类型参数之间的相互顺序的多样性,可能导致模板种类可能会超级多,感觉不是这样实现的,但又想不出来怎么搞的?疑惑中......

    

 

原文地址:https://www.cnblogs.com/cchust/p/2300344.html