oracle 11g PL/SQL Programming学习十四

----------------------------------------------------------------------------
-----------------PL/SQL学习笔记系列 By Cryking-----------------
------------------------转载请注明出处,谢谢!------------------------ 

 

4.使用C共享库
oracle为外部存储构建了一个可扩展的架构.
它非常灵活地支持任何能被C调用的编程语言.

  定义C共享库(需要熟悉简单的C语言)
  你将使用下面的C程序作为一个动态链接库(DLL)或共享库.
你需要安装一个C编译器来编译这个例子.
 writestr1.c文件内容

/* Include standard IO. */
#include <stdio.h>
/* Declare a writestr function. */
void writestr(char *path, char *message){
/* Declare a FILE variable. */
FILE *file_name;
/* Open the file in write-only mode. */
file_name = fopen(path,"w");
/* Write to file the message received. */
fprintf(file_name,"%s\n",message);
/* Close the file. */
fclose(file_name);
}

 

--编译一个C共享库
[oracle@oracleserver oracle]$ vi writestr1.c
[oracle@oracleserver oracle]$ gcc -shared -o writestr1.so writestr1.c
[oracle@oracleserver oracle]$ ls *.so
writestr1.so
[oracle@oracleserver oracle]$ mkdir $ORACLE_HOME/customlib
[oracle@oracleserver oracle]$ mv writestr1.so /u01/app/oracle/product/11.2.0/dbhome_1/customlib/


 
你应当注意上面的C程序没有main函数,它只是作为一个DLL或共享库使用.
注意上面的编译方法(不要直接使用 gcc -o编译,否则会报缺失main函数).

你需要在$ORACLE_HOME目录下创建一个自定义目录customlib.
你需要保证用户或组对customlib目录有读、写、执行的权限.

定义和调用PL/SQL Library Wrapper
首先,定义PL/SQL库.
  需要先在数据库定义外部库.(上面已经定义好,见listener.ora文件中的ENV参数.)
创建PL/SQL库语法原型为:
CREATE [OR REPLACE] LIBRARY <library_name> AS | IS
'<file_specification>'
AGENT '<agent_dblink>';
/

示例:

23:46:18 SYS@ORCL> CREATE OR REPLACE LIBRARY library_write_string AS
23:47:50   2  '/u01/app/oracle/product/11.2.0/dbhome_1/customlib/writestr1.so';
23:47:52   3  /

Library created.

Elapsed: 00:00:00.23

 

然后,建立PL/SQL library wrapper.
PL/SQL library wrapper主要用来定义一个数据库和外部存储的接口.
接口定义了PL/SQL参数和C数据类型的映射关系.
ORACLE提供额外的派生类型来支持OCI.

在PL/SQL和C数据类型转换之间存在以下限制:
  1.PL/SQL有NULL变量,但在C中没有对应的值.
    当一个变量可能为NULL时,你需要使用另外一个变量(指示器变量)来通知该变量是否为NULL。
    你使用OCI_IND_NULL和OCI_IND_NOTNULL来检查指示器变量是否为NULL.
  2.当数据交换时,C和PL/SQL都需要知道string字符串的长度.
    在处理二进制字符串时,你应当使用VSIZE来获得长度.
  3.当extproc代理运行在一个不同的数据库时,CHARSETID和CHARSETFORM受制于全球化的复杂性.
创建一个C Library Wrapper存储过程的语法:
CREATE [OR REPLACE] PROCEDURE name [parameter_list]
AS EXTERNAL
LIBRARY_NAME library_name
NAME "<external_library_name>"
AGENT IN [parameter_list]
WITH CONTEXT
PARAMETER [parameter_list];

下面的示例提出了一个比较独特的方法,使用隐式的SELF.
在PL/SQL,你不用去管理对象类型的SELF成员函数,因为它是隐式管理的.
如:

00:19:33 SYS@ORCL> CREATE OR REPLACE TYPE object_library_sample AS OBJECT(V NUMB
ER,member function get_tea_temperature return number);
00:21:06   2  /

Type created.

Elapsed: 00:00:00.45
--使用了上面创建好的library_write_string PL/SQL库
00:27:41 SYS@ORCL> CREATE OR REPLACE TYPE BODY object_library_sample AS
00:27:43   2    MEMBER FUNCTION get_tea_temperature RETURN NUMBER AS
00:27:43   3      LANGUAGE C NAME "tea_temp"
00:27:43   4      library library_write_string
00:27:43   5      WITH CONTEXT
00:27:43   6      PARAMETERS(CONTEXT,
00:27:43   7                 SELF   ,
00:27:43   8                 SELF    INDICATOR STRUCT,
00:27:43   9                 SELF    TDO,
00:27:43  10                 RETURN  INDICATOR);
00:27:43  11  END;
00:27:44  12  /

Type body created.

Elapsed: 00:00:00.19


创建PL/SQL外部存储.

00:27:45 SYS@ORCL> CREATE OR REPLACE PROCEDURE write_string(path VARCHAR2, message VARCHAR2) AS
01:00:25   2    EXTERNAL
01:00:25   3    LIBRARY library_write_string NAME "writestr"
01:00:25   4    PARAMETERS(path STRING, message STRING);
01:00:26   5  /

Procedure created.

Elapsed: 00:00:00.22

 

在你学会如何定义和配置PL/SQL wrapper前,你应当知道如何建立网络连接(配置监听)、编译共享库、代理配置等.
完成这些后,现在你要知道如何使用它。

--调用外部存储write_string
01:00:28 SYS@ORCL> BEGIN
01:05:19   2  write_string('/tmp/file.txt','Hello World!');
01:05:19   3  END;
01:05:21   4  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.29


 

根据之前建立的C共享库,可以知道执行该外部存储之后,会建立对应文件,写入传入的内容.
验证:

[oracle@oracleserver oracle]$ more /tmp/file.txt
Hello World!

 

使用外部存储时,有几点注意:
  1.你不应使用全局变量,因为它们不是线程安全的.
  2.你不应使用外部静态变量,因为它们不是线程安全的.
  3.你只能在支持DLL或共享库的平台上使用外部存储.
  4.你只能使用能被C调用的编程语言.
  5.当你需要传递游标或记录类型到外部存储的时候,你必须使用对象来传递
  6.你不能在PL/SQL wrapper的LIBRARY子句中使用DB_LINK.
  7.最多传递128个参数.其中浮点类型或双精度类型算2个参数.

 

5.使用JAVA共享库
oracle为外部存储构建了一个可扩展的架构.
它非常灵活地支持任何能被C调用的编程语言.
oracle直接支持java作为数据库的一部分.(除了oracle Express版)
java库不使用extproc,因为它们已经是本地oracle数据库的一部分了.
这简化了很多操作,但也带来了一些不便.(使用extproc代理和外部C库的时候)
java相比C,有几点优势:
  1.JAVA理解SQL类型.它避免了乏味的数据类型映射.
  2.JAVA是加载到oracle数据库里的.
    这样避免了文件管理问题和监听ENV参数进程,因为它不需要使用extproc代理.
  3.JAVA是本地线程安全的.
    它不需要你去处理那些线程的细微差别,避免了静态变量.
  4.JAVA不需要去管理内存地址.(也就是说JAVA没有指针)
java相比C,也有几点劣势:
  1.JAVA使用了SGA中的JAVA池来管理进程.而C外部存储使用它们自己的内存空间.
    换句话说就是C外部存储降低了SGA的内存消耗,而JAVA增加了SGA的负载.
  2.JAVA的速度比不上C.
    因为JAVA需要通过JVM来解释.
  3.JAVA限制对文件的访问.这是为了保护数据库的完整性.
    DBMS_JAVA包提供了一个方法来实现JAVA库程序的读写访问.
  4.使用java库的PL/SQL wrapper函数在方法定义上有限制.
    所有通过PL/SQL wrapper函数访问的JAVA class方法必须是静态的.
    这样支持PL/SQL wrapper函数的java库就不是线程安全的了.

下面来实现定义一个简单的java库.
首先,由于后面的程序包含了一个标准的I/O库,需要访问到外部物理文件.
所以需要先使用DBMS_JAVA.GRANT_PERMISSION来对相应目录进行授权.

01:51:44 SYS@ORCL>  BEGIN
01:52:16   2     DBMS_JAVA.GRANT_PERMISSION('SCOTT',
01:52:16   3                                'SYS:java.io.FilePermission',
01:52:16   4                                '/home/oracle/file.txt',
01:52:16   5                                'read');
01:52:16   6   END;
01:52:18   7  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:28.79


 

然后建立JAVA库.(你需要配置JAVA环境,也就是需要JDK+环境变量)
提示:这里可以直接利用ORACLE_HOME/JDK/BIN路径下的JAVAC来编译java文件.
编译ReadFile1.java,文件内容如下:

import java.io.*;

public class ReadFile1
{
// Convert the string to a file resource and call private method.
public static String readString(String s){
  return readFileString(new File(s)); }
// Read an external file.
  private static String readFileString(File file) {
// Define control variables.
  int c;
  String s = new String();
  FileReader inFile;
  try {
  inFile = new FileReader(file);
  while ((c = inFile.read()) != -1) {
  s += (char) c; }
     }
catch (IOException e) {
  return e.getMessage(); }
  return s; }
// Testing method.
public static void main(String[] args) {
  String file = new String("/tmp/file.txt");
  System.out.println(ReadFile1.readString(file)); }
}


将上面的java文件编译成ReadFile1.class后,使用loadjava工具将其加载到数据库中.

[oracle@oracleserver ~]$ ls ReadFile1*
ReadFile1.class
[oracle@oracleserver ~]$ loadjava -r -f -o -user scott/tiger ReadFile1.class
[oracle@oracleserver ~]$


没有提示,说明ReadFile1.class文件加载成功.

 

发布java库(也就是定义和使用PL/SQL Library Wrapper调用java库)
注意JAVA库和PL/SQL也有数据类型的映射.LONG和LONG RAW数据类型最大只能为32K.
大多数类型的映射是简单的.

--建立函数,发布java类ReadFile1
02:14:34 SCOTT@orcl> CREATE OR REPLACE FUNCTION read_string(file IN VARCHAR2)
02:14:40   2  RETURN VARCHAR2 IS
02:14:40   3    LANGUAGE JAVA NAME 'ReadFile1.readString(java.lang.String) return String';
02:14:43   4  /

Function created.

Elapsed: 00:00:00.23


使用函数read_string读取/home/oracle/file.txt文件的内容.

--先在文件中写点内容
[oracle@oracleserver ~]$ echo Just a test>>file.txt
[oracle@oracleserver ~]$ more file.txt
Just a test

--然后使用函数读取
02:21:20 SCOTT@orcl> SELECT read_string('/home/oracle/file.txt') a FROM dual;

A
---------------
Just a test

1 row selected.

Elapsed: 00:00:00.01



6.外部存储故障诊断
外部存储的失败通常是因为两种原因.
一是监听的配置,共享库的配置、或者环境的配置.
  以下错误比较常见:
  1.监听的ENV参数不正确.
  2.文件路径问题
  3.监听中EXTPROC_DLLS参数值问题
  4.extproc监听不正确或没有运行
  5.没有单独的extproc监听
  6.PL/SQL Wrapper定义的NAME值不正确
 
二是外部程序的定义和PL/SQL wrapper的定义不同.
  这一般是由于数据类型的不正确转换导致的.
如错误:
BEGIN
*
ERROR at line 1:
ORA-28576: lost RPC connection to external procedure agent
ORA-06512: at "PLSQL.WRITE_STRING", line 1
ORA-06512: at line 4
这种错误是由于数据类型不能隐式转换时发生.
也就是当你尝试使用实际参数来fork外部库时,隐式转换到库的形式参数时发生的错误.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作者:Steven Feuerstein, Bill Pribyl 出版日期:October 1, 2009 出版社:O'Reilly 页数:1226 ISBN:ISBN-10: 0596514468 ISBN-13: 978-0596514464 文件格式:PDF 文件大小:15.06 MB Review If you’re doing database application development in the Oracle environment, you’re going to have to know PL/SQL, the company’s extended query and update language. If you want your programs to exploit the special capabilities of Oracle software, you’ll need to know the language well. That’s where the third edition of Oracle PL/SQL Programming comes into play. It’s an absolutely comprehensive reference (as well as a rather extensive tutorial) on PL/SQL, ideally suited to answering your questions about how to perform some programming tasks and reminding you of the characteristics of functions, triggers, and other elements of the database programmer’s toolkit. The new edition covers calls to Java methods from within PL/SQL programs, autonomous transactions, object type inheritance, and the new Timestamp and XMLType data types. There’s also more information about server internals–the way PL/SQL programs are run–than before, better enabling readers to optimize their code for fast and safe execution. Steven Feuerstein takes care to explain, with prose and example code, the characteristics of PL/SQL elements. In explaining number conversions, for example, he explores Oracle’s different ways of formatting numbers, then details the behavior of the to_number function under different conditions (with and without a specified format model, and with National Language Support information attached). It’s a helpful approach that will have readers using the index to locate places in which Feuerstein mentions language elements of interest. –David Wall Topics covered: How to use Oracle PL/SQL in all its manifestations through Oracle9i. Fundamentals of program structure (loops, cases, exceptions, etc.) and execution get attention, as do data types, transaction management, triggers, and the object-oriented aspects of the language. There’s also coverage of calls to external Java and C programs. –This text refers to the Paperback edition. Product Description This book is the definitive reference on PL/SQL, considered throughout the database community to be the best Oracle programming book available. Like its predecessors, this fifth edition of Oracle PL/SQL Programming covers language fundamentals, advanced coding techniques, and best practices for using Oracle’s powerful procedural language. Thoroughly updated for Oracle Database 11g Release 2, this edition reveals new PL/SQL features and provides extensive code samples, ranging from simple examples to complex and complete applications, in the book and on the companion website. This indispensable reference for both novices and experienced Oracle programmers will help you: Get PL/SQL programs up and running quickly, with clear instructions for executing, tracing, testing, debugging, and managing PL/SQL code Optimize PL/SQL performance with the aid of a brand-new chapter in the fifth edition Explore datatypes, conditional and sequential control statements, loops, exception handling, security features, globalization and localization issues, and the PL/SQL architecture Understand and use new Oracle Database 11g features, including the edition-based redefinition capability, the function result cache, the new CONTINUE statement, fine-grained dependency tracking, sequences in PL/SQL expressions, supertype invocation from subtypes, and enhancements to native compilation, triggers, and dynamic SQL Use new Oracle Database 11g tools and techniques such as PL/Scope, the PL/SQL hierarchical profiler, and the SecureFiles technology for large objects Build modular PL/SQL applications using procedures, functions, triggers, and packages
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值