急问:如何用pro*C实现unix操作系统下的Oracle数据库表的导出

yichi 2004-10-09 02:15:07
如题:如何用pro*C实现unix操作系统下的Oracle数据库表的导出

环境,Hp_Unix
Oracle9i + Pro*C 编译环境
gcc编译环境

需要实现的功能是
以参数形式输入数据库名,用户名,密码,数据库中的表名,要保存的文件的路径及文件名。
将此表中的所有数据导出到指定的文本文件中。

导出的文件的格式要求是:
每一个记录做成一行。末尾为换行符。
char 和vchar型的数据按照左对齐,右侧没有达到数据库字段规定之长度的,用空格补齐
number型的数据右对齐,左侧没有达到数据库字段规定之长度的,用空格补齐

例子如下:

数据类型 位数 数据 文本文件中存储的数据
number 4 10 ————〉 △△10
char 9 abcde abcde△△△△





望各位给出完整的代码,如果可以给出注释就更好了:
谢谢各位高手了。

分不够可以再加!

我这里找到一个C++builder的例子,可是不会自己修改过来,
代码如下

...全文
286 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
Phontom 2004-10-12
  • 打赏
  • 举报
回复
关注一下,高手来解答吧

谁给提供个思路

yichi 2004-10-09
  • 打赏
  • 举报
回复
求各位高人帮忙啊!



小弟马上就要交差了,可是到现在还没有思路!
yichi 2004-10-09
  • 打赏
  • 举报
回复
/*---------------------------------------------------------------------------
导出文本函数
因为不确定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_CREAT|O_TEXT|O_APPEND|O_RDWR, S_IREAD|S_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;
}
yichi 2004-10-09
  • 打赏
  • 举报
回复
//-------------------------------------------------------------------------
//加入必要的头文件
#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\stat.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结构体请查相关资料*/

//如果在PROC中用到ORACA,还要在程序头加上 EXEC ORACLE OPTION (ORACA = YES);
EXEC ORACLE OPTION (ORACA = YES);
///*RELEASE_CURSOR=YES 使PROC 在执行完后释放与嵌入SQL有关资源*/
EXEC ORACLE OPTION (RELEASE_CURSOR = YES);

//说明ORACLE外部函数
extern "C" _declspec(dllimport) void _stdcall sqlclu(SQLDA*); ////释放空间使用函数free()释放由函数malloc()所分配的内存,使用函数sqlclu()释放为查询描述区以及绑定描述区所分配的空间
extern "C" _declspec(dllimport) void _stdcall sqlnul(short*, short*, int*);//将NUMBER的值重置为FLOAT或INT。T[i]的高位存储着第i个查询列表项的NULL\NOTNULL状态信息。在执行OPEN或FETCH命令前必须清除该位,这可以通过调用函数sqlnul()来完成。
extern "C" _declspec(dllimport) void _stdcall sqlprc(int*, int*, int*);//对于查询描述区来说,DESCRIBESELECT LIST命令会将长度数组设置为每个查询列表项的最大长度。各种数据类型的长度是各不相同的。对于CHAR或VARCHAR2类型的查询列表项来说, DESCRIBE SELECT LIST将L[i]设置为查询列表项的最大长度;而对于NUMBER类型的查询列表项来说,分别被保存到了,通过调用函数sqlpre()可以从L[i] 中读取到精度和标度值。函数sqlpre()的语法如下:sqlpre(long*length,int*precision,int*scale);该函数的原型在sqlcpr.h文件中。参数说明如下:·length:指向存储NUMBER值长度的长整数变量的指针。对于变量L来说,长度被存储到L[i]中,而精度和标度分别存储在该变量的低字节和高字节中。·precision:指向整数变量的指针,NUMBER值的精度返回到该变量中。·scale: 指向整数变量的指针,NUMBER值的标度返回到该变量中。该函数只能用于非线程应用。而如果要在线程应用中完成同样功能,则需要使用函数sqlprct()。另外,也可以使用SQLLIB的新函数SQLNumberProV6(),该函数既可用于线程应用又可用于非线程应用。
extern "C" _declspec(dllimport) struct SQLDA * _stdcall sqlald(int, unsigned int, unsigned int);//在定SQLDA结构后,为了使用查询描述区和绑定描述区,我们还必须使用函数sqlald()为它们分配内存。当分配描述区时,函数sqlald()会将V[0]到V[N-1]设置为0。该函数语法如下:

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;
}

3,491

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 高级技术相关讨论专区
社区管理员
  • 高级技术社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧