如题:如何用pro*C实现unix操作系统下的Oracle数据库表的导出环境,Hp_Unix
Oracle9i + Pro*C 编译环境
gcc编译环境需要实现的功能是
以参数形式输入数据库名,用户名,密码,数据库中的表名,要保存的文件的路径及文件名。
将此表中的所有数据导出到指定的文本文件中。导出的文件的格式要求是:
每一个记录做成一行。末尾为换行符。
char 和vchar型的数据按照左对齐,右侧没有达到数据库字段规定之长度的,用空格补齐
number型的数据右对齐,左侧没有达到数据库字段规定之长度的,用空格补齐例子如下:数据类型 位数 数据 文本文件中存储的数据
number 4 10 ————〉 △△10
char 9 abcde abcde△△△△ 望各位给出完整的代码,如果可以给出注释就更好了:
谢谢各位高手了。分不够可以再加!我这里找到一个C++builder的例子,可是不会自己修改过来,
代码如下
Oracle9i + Pro*C 编译环境
gcc编译环境需要实现的功能是
以参数形式输入数据库名,用户名,密码,数据库中的表名,要保存的文件的路径及文件名。
将此表中的所有数据导出到指定的文本文件中。导出的文件的格式要求是:
每一个记录做成一行。末尾为换行符。
char 和vchar型的数据按照左对齐,右侧没有达到数据库字段规定之长度的,用空格补齐
number型的数据右对齐,左侧没有达到数据库字段规定之长度的,用空格补齐例子如下:数据类型 位数 数据 文本文件中存储的数据
number 4 10 ————〉 △△10
char 9 abcde abcde△△△△ 望各位给出完整的代码,如果可以给出注释就更好了:
谢谢各位高手了。分不够可以再加!我这里找到一个C++builder的例子,可是不会自己修改过来,
代码如下
解决方案 »
- 测试oracle连接出现的小问题,纠结了半天没找出,汗
- 关于这条语句的优化方案 谢谢大家 优化一下性能
- 用chmod -R 777 oracle目录执行后,oracle启动不起来了怎么办?
- oracle几道单选题目2
- oracle varchar2(45)只能插入10个汉字,怎么回事?
- 新手请教Oracle性能指标问题?在线等,谢谢!
- 跟踪sessioin的结果,有两个疑问?
- 在线请教关于spool的文本导出结果问题:
- 为何服务器死掉
- Oracle不支持 “Ø” 这个特殊符号
- 请问Oracle语句级别的Trigger中,如何标识被修改、删除、插入的行?谢谢
- MS-SQL语法 转 ORACLE语法 顶!
//加入必要的头文件
#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;
}
导出文本函数
因为不确定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;
}