用户名:  密码:
兄弟在线   

标题:利用LOB字段存取操作系统二进制文件

作者:佚名 来源:网络 时间:2013-03-17

    在Oracle 8i的SQL*Plus中如何利用LOB字段存取操作系统二进制文件

                                                  
     广东省岭澳核电有限公司工程控制处管理信息科(518124)  黄福同
          

Oracle 8i数据库系统功能比前面版本更加完善,尤其是出现了BLOB,CLOB,NCLOB,
BFILE这些LOB(大型对象)类型来取代功能有限的LONG、LONGRAW类型。BLOB字段最
大长度为4G(4,294,967,295)字节,而且不再象LONGRAW那样每个表中只是限制有一
个字段是LONGRAW(最长2G)型的。BLOB,CLOB,NCLOB为内部BLOB(数据通常在数据
库中存放),BFILE为外部LOB(所存储的只是指向外部操作系统文件的指针),用户可
以使用PL/SQL的包DBMS_LOB来处理LOB数据,但是遗憾的是,DBMS_LOB包只能将二进
制操作系统文件写入到BLOB字段中,却无法将BLOB字段中的二进制操作系统文件取回
到操作系统中,估计将来会有所改善。本文将就如何在SQL*Plus将WORD文件存入取出
ORACLE中作详细解释说明,供各位同行参考。

实验的软件环境如下:Windows 2000 Advanced Server,Oracle 8.1.7,VC++6.0+SP5
硬件环境如下:双PIII866 CPU,768M内存

在internal这个用户下给scott用户授权如下:
SQL>grant create any directory to scott;
SQL>grant create any library to scott;
在scott这个用户下执行下述语句:

SQL>create table bfile_tab (bfile_column BFILE);
SQL>create table utl_lob_test (blob_column BLOB);
SQL>create or replace directory utllobdir as 'C:\DDS\EXTPROC';
SQL>set serveroutput on

然后执行下面语句就将C:\DDS\EXTPROC目录下的word文件COM.doc存入到utl_lob_test
表中的blob_column字段中了。

declare
   a_blob  BLOB;
   a_bfile BFILE := BFILENAME('UTLLOBDIR','COM.doc'); --用来指向外部操作系统

文件
begin
   insert into bfile_tab values (a_bfile)
     returning bfile_column into a_bfile;
   insert into utl_lob_test values (empty_blob())
     returning blob_column into a_blob;
   dbms_lob.fileopen(a_bfile);
   dbms_lob.loadfromfile(a_blob, a_bfile, dbms_lob.getlength(a_bfile));
   dbms_lob.fileclose(a_bfile);
   commit;
end;
/
SQL>show errors
此时可以使用DBMS_LOB包的getlength这个procedure来检测是否已经将该word文件存入
到blob字段中了。如:
SQL> select dbms_lob.getlength(blob_column) from UTL_LOB_TEST;
结果如下:
DBMS_LOB.GETLENGTH(BLOB_COLUMN)
-------------------------------
                83968
说明该word文件已经存入到blob字段中去了。

下面将就如何取出该word文件到操作系统下作详细解释:
Oracle8.1.7只能用pro*c与OCI来实现该任务,所以Oracle服务器端必须支持pro*c
以及外部library,Oracle8.1.7数据库默认安装为支持pro*c以及外部Procedure,
用户可以自己检查一下listener.ora 和 tnsnames.ora这两个文件。
listener.ora中包含如下语句:
SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = D:\oracle\ora81)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (GLOBAL_DBNAME = hft)
      (ORACLE_HOME = D:\oracle\ora81)
      (SID_NAME = hft)
    )
  )
tnsnames.ora中包含如下语句:
EXTPROC_CONNECTION_DATA =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
    )
    (CONNECT_DATA =
      (SID = PLSExtProc)
      (PRESENTATION = RO)
    )
  )

下面这个文件为lob2file.c,具体作用是将BLOB中的二进制文件倒出到操作系统中。
/*begin of  lob2file.c*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <oci.h>
#include <ociextp.h>
#define  DEFAULT_CHUNK_SIZE  1024
static   int     logging;
static   char    logfile[512];
static   FILE   *logfilep = NULL;
int lob2file ( OCILobLocator     *a_lob,    /* the LOB */
               short              lbind,    /* LOB indicator */
               char              *path,     /* file to write */
               short              pind,     /* file indicator */
               int                plen,     /* filename length */
               char              *lpath,    /* logfile name */
               short              lpind,    /* logfile indicator */
               int                lplen,    /* logfile name length */
               int                logit,    /* logging enabled? */
               OCIExtProcContext *ctxt      /* OCI Context */
             )
{
   sword      errnum = 0;
   OCIEnv    *envhp = NULL;
   OCISvcCtx *svchp = NULL;
   OCIError  *errhp = NULL;
   char       lobfile[512];
   FILE      *lobfilep = NULL;
   /*
    * If required, open the log file for writing
    * Use the user provided logfile name if possible
    * Otherwise, default the logfile to lob2file.log
    */
   logging = logit;
   if (logging)
   {
      if (lpind == -1 || lplen == 0 || lplen >= 512)
      {
         strcpy(logfile, "lob2file.log");
      }
      else
      {
         strncpy(logfile, lpath, lplen);
         logfile[lplen] = '\0';
      }
      logfilep = fopen(logfile, "w");
      if (logfilep == NULL)
      {
         if ((logfilep = fopen("lob2file.log", "w")) != NULL)
         {
            fprintf(logfilep, "Error: Unable to open logfile %s\n",

logfile);
            fprintf(logfilep, "Error: errno = %d\n", errno);
         }
      }
   }
   /*
    * Retrieve the environment, service context, and error handles
    */
   if ((errnum = OCIExtProcGetEnv(ctxt, &envhp,
                                  &svchp, &errhp)) != OCIEXTPROC_SUCCESS)
   {
      if (logging && logfilep != NULL)
      {
          fprintf(logfilep, "Error: Call to OCIExtProcGetEnv failed\n");
          fprintf(logfilep, "Error: OCIExtProcGetEnv returned %d\n",

errnum);
          fclose(logfilep);
          return -1;
      }
   }
   /*
    * Verify that the user has provided a name for the output file
    */
   if (pind == -1 || plen == 0)
   {
      char *errmsg = "Pathname is null or empty string";
      if (logging && logfilep != NULL)
      {
         fprintf(logfilep, "Error: %s\n", errmsg);
         fclose(logfilep);
      }
      errnum = 20001;
      OCIExtProcRaiseExcpWithMsg(ctxt, errnum, (text *)errmsg,

 

[1] [2] [3] 下一页



编辑:admin 总点击 [792]   评论  0 查看评论
上一篇:RedHat下Oracle启动脚本的建立
下一篇:Oracle数据库的后台进程管理技术介绍
【关闭窗口】
您可能感兴趣的文章
我要评论
          
评论标题:   可以输入250
 
验证数字: 2 + 6 =
兄弟友情提示
· 请自觉遵守国家有关法律、法规,尊重网上道德。
· 兄弟在线坚决抵制不良言行,违者文责自负。
· 如果文章有版权或其他问题等,请联系我们,我们会尽快处理。
· 文章注名来自网络的旨在传播共享信息,不做其它用途;注名原创的本站支持原创,但不代表同意其观点。
· 兄弟在线拥有管理用户与其文章和评论的一切权利,并有权在网站内转载或引用。
兄弟在线
兄弟热门文章
兄弟推荐文章
兄弟站内搜索

兄弟感兴趣的文章
兄弟最新影视