在数据库中自定义外部函数

在oracle中可以使用pl/sql来实现一些复杂的功能,同时可以通过自定义的外部函数来实现很多丰富的功能,我们可以基于c/c++来写一些函数,然后把动态链接库放入ORACLE_HOME中方便直接调用。
首先这种实现方法需要依赖于数据库层面的服务extproc,监听器会生成一个extproc进程,然后专门来处理外部函数的调用。
具体的配置可以在$ORACLE_HOME/network/admin下的listener.ora和tnsnames.ora中体现。
一般通过dbca创建的库都会默认配置extproc的部分,可以看到它使用的是ipc协议而不是tcp协议。
样例如下:

listener.ora
LIST=
  (DESCRIPTION=
    (ADDRESS_LIST=
      (ADDRESS=(PROTOCOL=tcp)(HOST=rac1)(PORT=1599))
      (ADDRESS=(PROTOCOL=ipc)(KEY=extproc))))
SID_LIST_LIST=
  (SID_LIST=
     (SID_DESC=
        (GLOBAL_DBNAME=TEST01)
        (ORACLE_HOME=/u03/ora11g/product/11.2.0/dbhome_1)
        (SID_NAME=TEST01)))

tnsnames.ora

EXTPROC01=
(DESCRIPTION=
 (ADDRESS=(PROTOCOL=ipc)(key=extproc))
 (CONNECT_DATA=(SERVICE_NAME=TEST01))
)

如果配置没有问题,可以使用tnsping来验证一下服务是否可用。
[ora11g@rac1 admin]$ tnsping extproc01
TNS Ping Utility for Linux: Version 11.2.0.3.0 - Production on 24-FEB-2015 06:03:53
Copyright (c) 1997, 2011, Oracle.  All rights reserved.
Used parameter files:
Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION= (ADDRESS=(PROTOCOL=ipc)(key=extproc)) (CONNECT_DATA=(SERVICE_NAME=TEST01)))
OK (0 msec)

接下来我们来实现一个简单的函数,大过年的我们就以红包为例。我们传入红包的金额,直接放大100倍。比如传入8块,直接输出800.

cat test.c
test(n)
int n;
{
     int lucky_money;
     lucky_money=100*n;
     return (lucky_money);
}

对编写的c程序做编译,生成动态链接库文件,然后直接拷贝到$ORACLE_HOME/bin下
[ora11g@rac1 extproc]$ cc -shared -o test.so test.c
[ora11g@rac1 extproc]$ ll
total 12
-rw-r--r-- 1 ora11g dba   83 Feb 24 05:42 test.c
-rwxr-xr-x 1 ora11g dba 5609 Feb 24 05:42 test.so
[ora11g@rac1 extproc]$ cp test.so $ORACLE_HOME/bin

这个时候我们就开始创建库文件,指向test.so,然后把权限赋予指定的用户。
SQL> create  or replace library test_code as '$ORACLE_HOME/bin/test.so';
    /
Library created.

SQL> grant execute on test_code to n1;
Grant succeeded.

有了库文件,我们就开始定义函数,这个函数最终给会调用链接库文件
create or replace function func_test
(x binary_integer)
return binary_integer
as language C
library sys.test_code
name "test";

到此为止就大功告成了,我们的函数就创建成功了,来简单验证一下。
set serveroutput on
var lucky_money number;
var amount number;
exec :lucky_money :=8888;
exec :amount := func_test(8888);
print amount;
SQL>
    AMOUNT
----------
    888800

这种方式能够屏蔽代码层的抽象,直接开放丰富的功能,还是比较实用的。

时间: 2024-09-28 04:29:06

在数据库中自定义外部函数的相关文章

在SQL Server数据库中拆分字符串函数

SQL Server数据库中拆分字符串函数的具体方法: CREATE FUNCTION uf_StrSplit '1.1.2.50','.' (@origStr varchar(7000), --待拆分的字符串 @markStr varchar(100)) --拆分 标记,如',' RETURNS @splittable table ( str_id varchar(4000) NOT NULL, --编号ID string varchar(2000) NOT NULL --拆分后的字符串 )

数据库中的聚集函数文体

问题描述 数据库中的聚集函数文体 聚集函数前面为什么加select,感觉没必要吧,直接把要查询的参数传给它了 解决方案 一个聚集函数从多个输入行中计算出一个结果. 比如,我们有在一个行集合上计算 count(数目), sum(和),avg(均值), max(最大值)和min(最小值)的函数. select是必要的,目前的数据库都需要这个

js类中获取外部函数名的方法_javascript技巧

比如我们要在一个类中设定一个方法可以根据调入一个方法保存在类变量中,等需要的时候可以通过访问类变量来得到. 通常如果我们生成一个实例 如:var temp=new TopnetTree(); 如果我们通过设定属性的方式来传入一个方法,会发现传入的是一个函数的内容,而非函数名. 如temp.fileAction=fnTest; //fnTest是一个函数 于是偶就写了一个方法来实现此功能. 通过arguments来判断判断传入内容: 实现如下功能: 传入内容为空,不执行任何内容 传入一个参数,则表

js类中获取外部函数名的方法与代码_js面向对象

比如我们要在一个类中设定一个方法可以根据调入一个方法保存在类变量中,等需要的时候可以通过访问类变量来得到. 通常如果我们生成一个实例 如:var temp=new TopnetTree(); 如果我们通过设定属性的方式来传入一个方法,会发现传入的是一个函数的内容,而非函数名. 如temp.fileAction=fnTest; //fnTest是一个函数 于是偶就写了一个方法来实现此功能. 通过arguments来判断判断传入内容: 实现如下功能: 传入内容为空,不执行任何内容 传入一个参数,则表

数据库中的事务、存储过程和触发器的简单使用

什么是事务(Transaction) 指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)--也就是由多个sql语句组成,必须作为一个整体执行 这些sql语句作为一个整体一起向系统提交,要么都执行.要么都不执行 语法步骤: 开始事务:BEGIN TRANSACTION 事务提交:COMMIT TRANSACTION 事务回滚:ROLLBACK TRANSACTION 判断某条语句执行是否出错: 全局变量@@ERROR: @@ERROR只能判断当前一条T-SQL语句执行是否有错,为了判

qt-QT线程内调用外部函数发送信号是否有正确?多线程调用外部函数需要注意哪些问题?

问题描述 QT线程内调用外部函数发送信号是否有正确?多线程调用外部函数需要注意哪些问题? 大家好,我在QT多线程编程时,在线程内部调用了一个外部函数,外部函数中使用了emit来发送信号,请问这样是否会存在问题?另外,在线程中调用外部函数时需要注意哪些问题? 解决方案 我编写的代码大概如下: class myThread:public QThread; class DeviceScaner:public QObject { Q_OBJECT public: DeviceScaner(); ~Dev

简单讲解C++的内部和外部函数以及宏的定义_C 语言

C++内部函数和外部函数 函数本质上是全局的,因为一个函数要被另外的函数调用,但是,也可以指定函数只能被本文件调用,而不能被其他文件调用.根据函数能否被其他源文件调用,将函数区分为内部函数和外部函数. 内部函数 如果一个函数只能被本文件中其他函数所调用,它称为内部函数.在定义内部函数时,在函数名和函数类型的前面加static.函数首部的一般格式为: static 类型标识符 函数名(形参表); 如 static int fun(int a, int b); 内部函数又称静态(static)函数.

数据库快照,自定义函数与计算列

数据库快照,自定义函数与计算列 1.数据库快照 数据库快照就是保存某个数据库在快照那一瞬间的状态.快照和备份原理上有所不同,但是功能有一点相同那就是可以将数据还原为备份的那个时刻.快照的原理是新建一个数据库指针,在原数据库没有变化的情况下快照是不占用空间的,而数据库发生了变化,那么在变化前,被修改的数据页会先复制一份到快照文件中,然后再对原数据页进行修改.显然这样做的好处就是比备份数据库占用空间小.快照是只读的,你可以直接在SQL语句中把他当数据库用: use snap1;--使用快照 sele

sql server中自定义函数

create function getZHYE(@NM varchar(300)) returns FLOAT as begin Declare @memberName FLOAT set @memberName='0' select @memberName = 字段1 from 表A where 字段2=@NM if @memberName='0' begin set @memberName='0' end else if @memberName !='0' begin set @member