网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > 数据库 > Oracle教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
数据库:数据库教程,数据库技巧,Oracle教程,MySQL教程,Sybase教程,Access教程,DB2教程,数据库安全,数据库文摘
本月文章推荐
.Oracle XMLDB 占用了8080端口.
.一些常用的计划脚本(1).
.获得SQL表述式的详细信息.
.oracle下导出某用户所有表的方法.
.构建您自己的Oracle RAC 10g集群.
.Oracle数据类型简介.
.oracle8.16在RedHat7.1上的安装步.
.Oracle9i 数据库管理实务讲座(三).
.ORACLE在HP-UX下的系列问题处理(.
.Oracle9i 性能调整与优化(1).
.ORACLE在HP_UX下的系列问题处理(.
.Oracle10g自动归档的设置.
.关于oracle 10G企业网格计算的介.
.角斗士般的Oracle性能.
.ORACLE常用傻瓜问题1000问全集(.
.创建索引对SQL语句执行的影响.
.用Forms编写的数字时钟.
.修改默认的undo_retention参数设.
.Oracle数据库PL/SQL过程调试的输.
.Oracle数据库技术(7).

PROC++批量导入导出ORACLE数据库表

发表日期:2008-2-9



  
最近在开发一个项目中,为了解决数据库IO瓶颈,不得不把数据库中的数据导出为文本文件。文本传到客户端后又要导入到数据库。本人用C++Builder嵌入PROC++写了一个导入导出的DLL。假如对你有用深感荣幸!具体内容如下:

 

一、预备工作

计算机环境:Win 2000 PRO,Oracle 9i,C++ Builder 5.5

引入必要的ORACLE内部函数:要用的函数在$(ORACEL_HOME)\bin qlora9.dll链接库中。为了能在C++ Builder中使用,先得生成LIB:implib sqlora9.lib sqlora9.dll

 

二、源文件分析

//-------------------------------------------------------------------------

//加入必要的头文件

#include<vcl.h> #include<windows.h> #include<stdio.h> #include<stdlib.h> #include<string.h>

#include<time.h> #include<math.h> #include<fcntl.h> #include<io.h> #include<sys tat.h>

//说明DLL的输出函数

extern "C" _declspec(dlleXPort) int _stdcall ConnectDB(const char *Username,

                                const char *PassWord, const char *Dbname);

extern "C" _declspec(dllexport) int _stdcall ImportTxtfile(TList *LengthArray,

                                String *FieldArray, const char *TableName,

                                const char *FileName);

extern "C" _declspec(dllexport) int _stdcall ExportTxtfile(const char *Sql,

                                const char *FileName);

#pragma hdrstop

//----------------------------------------------------------------------------

#define MAX_ITEMS 20        //定义最大字段数

#define MAX_VNAME_LEN 30  //定义选择表项最大长度

#define MAX_INAME_LEN 30  //定义指示器变量名字的最大长度

 

EXEC SQL INCLUDE sqlca;    //说明SQL通讯区

EXEC SQL INCLUDE oraca;    //说明ORACLE通讯区

EXEC SQL INCLUDE sqlda;    //说明SQL语句描述结构/*SQLDA结构体请查相关资料*/

 

EXEC ORACLE OPTION (ORACA = YES);

EXEC ORACLE OPTION (RELEASE_CURSOR = YES);

 

//说明ORACLE外部函数

extern "C" _declspec(dllimport) void _stdcall sqlclu(SQLDA*);

extern "C" _declspec(dllimport) void _stdcall sqlnul(short*, short*, int*);

extern "C" _declspec(dllimport) void _stdcall sqlprc(int*, int*, int*);

extern "C" _declspec(dllimport) strUCt SQLDA * _stdcall sqlald(int, unsigned int, unsigned int);

 

SQLDA *SelectUnit;  //定义选择项描述

SQLDA *BindUnit;  //定义输入项空间

//定义变量,以存放连接数据库的参数

EXEC SQL BEGIN DECLARE SECTION;

    char User[20];//用户名

    char Pwd[20];//密码

    char DB[20];//数据库服务名

EXEC SQL END DECLARE SECTION;

 

bool bConnect = false;//是否连接标志

#pragma hdrstop

 

#pragma argsused

//C++ Builder DLL的主函数

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)

{

        return 1;

}

 

/*---------------------------------------------------------------------------

    连接数据库

---------------------------------------------------------------------------*/

int _stdcall ConnectDB(const char *Username, const char *Password,

                                   const char *Dbname)

{

  strcpy(User, Username);

  strcpy(Pwd, Password);

  strcpy(DB, Dbname);

 

  EXEC SQL CONNECT :User IDENTIFIED BY :Pwd USING :DB;

 

  if (sqlca.sqlcode < 0)

    return -1;

 

  bConnect = true;

  return 0;

}

/*---------------------------------------------------------------------------

导出文本函数

因为不确定SELECT语句的表及字段,所以我使用动态语句(ORACLE DYNAMIC SQL)的//第四种方式。
动态SQL方法四是在不确定SQL语句的选择项与输入项,且不知个数与数据类型的情况下使用的一种复杂程序设计技术。

---------------------------------------------------------------------------*/

int _stdcall ExportTxtfile(const char *Sql/*SQL选择语句*/, const char FileName/*导出目标文本文件名*/)

{

  int null_ok, precision, scale;

 

  int handle;

 

  if ((handle = open(FileName, O_CREATO_TEXTO_APPENDO_RDWR, S_IREADS_IWRITE)) == -1)

  {

    //文件打开出错

    return -1;

  }

//定义变量,以存放SQL语句

  EXEC SQL BEGIN DECLARE SECTION;

    char sqlstr[256];

  EXEC SQL END DECLARE SECTION;

 

  //检查是否连接数据库

  if (bConnect == false) return -2;

 

  strcpy(sqlstr/*.arr*/, Sql);

  //  sqlstr.len = strlen(sql);

 

  //给描述区分配空间 

  if ((SelectUnit = sqlald(MAX_ITEMS, MAX_VNAME_LEN, MAX_INAME_LEN)) == (SQLDA *)NULL)

  {

    //空间分配失败

    return -3;

  }

 

  if ((BindUnit = sqlald(MAX_ITEMS, MAX_VNAME_LEN, MAX_INAME_LEN)) == (SQLDA *)NULL)

  {

    //空间分配失败

    return -3;

  }

  //给查询返回值存储区分配空间

  SelectUnit->N = MAX_ITEMS;

  for (int i=0; i < MAX_ITEMS; i++)

  {

    BindUnit->I[i] = (short *)malloc(sizeof(short *));

    BindUnit->V[i] = (char *)malloc(MAX_VNAME_LEN);

  }

  for (int i=0; i < MAX_ITEMS; i++)

  {

    SelectUnit->I[i] = (short *)malloc(sizeof(short *));

    SelectUnit->V[i] = (char *)malloc(MAX_VNAME_LEN);

  }

 

  EXEC SQL WHENEVER SQLERROR GOTO sqlerr;//DO sql_error("导出出错");

//设置SQL语句

  EXEC SQL PREPARE SQLSA FROM :sqlstr;

  EXEC SQL DECLARE Cursorbase CURSOR FOR SQLSA;

 

  //输入描述处理

  BindUnit->N = MAX_ITEMS;

  EXEC SQL DESCRIBE BIND VARIABLES for SQLSA INTO BindUnit;

 

  if (BindUnit->F < 0)

  {

    return -4;

    //输入项过多

  }

  BindUnit->N = BindUnit->F;

  //打开光标

  EXEC SQL OPEN Cursorbase USING DESCRIPTOR BindUnit;

 

  //选择项处理

  EXEC SQL DESCRIBE SELECT LIST for SQLSA INTO SelectUnit;

 

  if (SelectUnit->F < 0)

  {

    return -4;

    //选择表项过多

  }

  SelectUnit->N = SelectUnit->F;

//因为所有格式,类型都是不确定的,所以要得到正确的返回值就要处理格式

  for (int i=0; i < SelectUnit->F; i++)

  {

    sqlnul(&(SelectUnit->T[i]), &(SelectUnit->T[i]), &null_ok);

    switch (SelectUnit->T[i])

    {

           case 1://CHAR

                break;

           case 2://NUMBER

                sqlprc(&(SelectUnit->L[i]), &precision, &scale);

                if (precision == 0)

                  precision = 40;

                SelectUnit->L[i] = precision + 2;

                break;

        case 8://LONG

             SelectUnit->L[i] = 240;

             break;

        case 11://ROWID

             SelectUnit->L[i] = 18;

             break;

        case 12://DATE

             SelectUnit->L[i] = 9;

             break;

        case 23://RAW

             break;

        case 24://LONGRAW

             SelectUnit->L[i] = 240;

             break;

     }

 

     SelectUnit->V[i] = (char *)realloc(SelectUnit->V[i], SelectUnit->L[i]+1);

 

     SelectUnit->T[i] = 1;//把所有类型转换为字符型

  }

 

  EXEC SQL WHENEVER NOT FOUND goto EndFor;

 

  for (;;)

  {

    EXEC SQL FETCH Cursorbase USING DESCRIPTOR SelectUnit;

 

    //输出各字段

    for (int i=0; i < SelectUnit->F; i++)

    {

      char buffer[256];

 

      if (i != SelectUnit->F-1)

        sprintf(buffer, "%s", SelectUnit->V[i]);

      else sprintf(buffer, "%s\r\n", SelectUnit->V[i]);

 

      int length = strlen(buffer);

 

      if (write(handle, buffer, length) != length)

      {

        return -5;

        //写文件失败 exit(1);

      }

    }

 

  }

 

EndFor:

 

  close(handle);

 

  for (int i=0; i < MAX_ITEMS; i++)

  {

    if (SelectUnit->V[i] != (char *)NULL)

      free(SelectUnit->V[i]);

 

    free(SelectUnit->I[i]);

  }

 

  for (int j=0; j < MAX_ITEMS; j++)

  {

    if (BindUnit->V[j] != (char *)NULL)

      free(BindUnit->V[j]);

 

    free(BindUnit->I[j]);

  }

 

  sqlclu(SelectUnit);

  sqlclu(BindUnit);

 

  EXEC SQL CLOSE Cursorbase;

 

  return 0;

 

sqlerr:

  return -6;

}

 

/*----------------------------------------------------------------------------

导入文本

为了批量导入,在此我调用的sqlldr工具

首先生成SQL*Loader控制文件,后运行sqlldr

----------------------------------------------------------------------------*/

int _stdcall ImportTxtfile(TList LengthArray/*导入文本的字段长度链表*/,

String *FieldArray/*数据库表的了段名数组*/, const char TableName/*导入的目标表*/, const char FileName/*导入的源文本文件*/)

{

  //产生SQL*Loader控制文件

  FILE *fout, *fp;

  char Execommand[256];

 

  char sqlload[] = ".\ qlload.ctl";

 

  //检查是否连接数据库

  if (bConnect == false) return -2;

 

  if ((fout=fopen(sqlload, "w")) == NULL)

  {

    //建立控制文件出错

    return -1 ;

  }

 

  fprintf(fout, "LOAD DATA\n");

  fprintf(fout, "INFILE '%s'\n", FileName);

  fprintf(fout, "APPEND INTO TABLE %s (\n", TableName);

 

  int iStart = 1;

  for(int i=0; i < LengthArray->Count; i++)

  {

    fprintf(fout, "%11s POSITION(%d:%d)", FieldArray[i], iStart, *(int*)LengthArray->Items[i]+iStart-1);

    iStart += *(int*)LengthArray->Items[i];

    fprintf(fout, " CHAR");

 

    if(i < LengthArray->Count-1)

      fprintf(fout, ",\n");

  }

  fprintf(fout, ")\n");

  fclose(fout);

 

  sprintf(Execommand, "sqlldr.exe userid=%s/%s@%s control=%s",

                      User, Pwd, DB, sqlload);

 

  if (system(Execommand) == -1)

  {

    //SQL*Loader执行错误

    return -1;

  }

 

  return 0 ;

}

 

 

//----------------------------------------------------------------------------

三、编译

用ORACLE的PROC预编译器预编后,放入C++ Builder中联编。
联编时需加入前面生成的sqlora9.lib。联编时还要注重,所有PROC生成的ORACLE内部函数调用都要说明为extern "C" _declspec(dllexport) TYPE _stdcall类型。

 

水平有限还请见谅!!!请多多指点。QQ:5005647

 
上一篇:Oracle 9i Installation on Red Hat Linux 人气:752
下一篇:Oracle 10G First Release的新特性简介(下) 人气:604
浏览全部Oracle教程的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐