通过在过程化编程语言中嵌入SQL语句而开发出的应用程序称为Pro程序。
在C/C++语言中嵌入SQL语句而开发出的应用程序称为Pro*C/C++程序。
–在通用编程语言中使用的SQL称为嵌入式SQL;
–在SQL标准中定义了多种语言的嵌入式SQL。
宿主语言 Pro程序
C/C++ Pro*C/C++
FORTRAN Pro*FORTRAN
PASCAL Pro*PASCAL
COBOL Pro*COBOL
ProC/C++预编译程序
–完成pc源程序到c/c++源程序的转换。
基本命令格式
PROC INAME=filename [OptionName1=value1]…[OptionNameN=valueN]
proc常用选项说明
选项 |
值 |
说明 |
INAME |
Filename |
proc源文件名称 |
INCLUDE |
Pathname |
指示proc去哪里找#include中包含的头文件 |
ONAME |
Filename |
预编译完成后输出文件名称 |
CPOOL |
YES,NO |
是否支持连接共享 |
MODE |
ANSI,ISO,ORACLE |
代码对 Oracle 或 ANSI 规则的顺应性 |
CODE |
ANSI_C,CPP,KR_C |
所要生成的代码类型 |
PARSE |
FULL,PARITIAL,NONE |
控制对哪一 非 SQL 代码进行语法分析 |
THREADS |
YES,NO |
是否支持多线程的应用程序 |
–在命令行输入不带选项的proc命令就可以列出所有选项以及当前默认值
–proc 选项=?就可以查看选项说明
gcc或者g++链接时需要增加
-L${ORACLE_HOME}/lib –lclntsh
指示编译器需要链接相关的库文件
开发之前先写一个适合proc使用的makefile
首先定义几个常量 .SUFFIXES: .c .o CC=gcc PROC=proc PROCSRCS=oracle.pc SRCS=$(PROCSRCS:.pc=.c) OBJS=$(SRCS:.c=.o) ORACLE_HOME=/opt/oracle/product/11.2.0 ORAFLAGS1=/usr/include/linux ORAFLAGS2=/usr/lib/gcc/i686-redhat-linux/4.4.4/include
定义编译命令 EXEC=abc all: $(OBJS) $(CC) -L${ORACLE_HOME}/lib -lclntsh -o $(EXEC) $(OBJS) @echo '^_^ ^_^ ^_^ ^_^ ^_^ ^_^ OK ^_^ ^_^ ^_^ ^_^ ^_^ ^_^' .c.o: $(SRCS) $(CC) -Wall -g -o $@ -c $< $(SRCS): ${PROC} INAME=$(PROCSRCS) INCLUDE=$(ORAFLAGS1) INCLUDE=$(ORAFLAGS2) CPOOL=YES MODE=ANSI CODE=ANSI_C PARSE=PARTIAL THREADS=YES ONAME=$(SRCS) clean: rm -f $(OBJS) rm -f $(SRCS)
使用proc编程步骤
–头文件包含和相关说明定义;
–安装错误处理函数;
–初始化数据库;
–连接到数据库;
–执行SQL语句;
–断开连接;
–释放相关资源。
pc文件的编写
首先包含三个最基本的头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
pc文件中如果在内嵌SQL语句中使用的变量,一定需要在EXEC SQL BEGIN DECLARE SECTION块语句中申明:
EXEC SQL BEGIN DECLARE SECTION;
sql_context pContext;
long SQLCODE;
EXEC SQL END DECLARE SECTION;
安装错误处理函数: extern void sqlglmt(void*, char*, size_t*, size_t* ); void sql_error() { char sErrorString[512]; size_t tMessageSize = 0; size_t tErrorSize = sizeof(sErrorString); memset(sErrorString, 0, sizeof(sErrorString)); sqlglmt(pContext, sErrorString, &tErrorSize, &tMessageSize); sErrorString[tMessageSize] = 0; printf("%s ", sErrorString); }
初始化数据库: void sql_init() { SQLCODE = 0; pContext = NULL; EXEC SQL ENABLE THREADS; EXEC SQL CONTEXT ALLOCATE :pContext; EXEC SQL CONTEXT USE :pContext; }
连接到数据库: int sql_connect(const char *User, const char *Password, const char *DBName) { EXEC SQL BEGIN DECLARE SECTION; const char *sUser; const char *sPassword; const char *sServer; EXEC SQL END DECLARE SECTION; SQLCODE = 0; sUser = User; sPassword = Password; sServer = DBName; EXEC SQL CONNECT :sUser IDENTIFIED BY :sPassword USING :sServer; if (SQLCODE != 0) { sql_error(); return 1; }else return 0; }
执行一个非SELECT SQL语句: int sql_exec(const char *DySQL) { EXEC SQL BEGIN DECLARE SECTION; const char *sDySQL; EXEC SQL END DECLARE SECTION; SQLCODE = 0; sDySQL = DySQL; EXEC SQL EXECUTE IMMEDIATE :sDySQL; if (SQLCODE != 0) { sql_error(); return 1; }else { return 0; } }
提交事务: int sql_commit() { SQLCODE = 0; EXEC SQL COMMIT WORK; if (SQLCODE != 0) { sql_error(); return 1; }else { return 0; } }
回滚事务: int sql_rollback() { SQLCODE = 0; EXEC SQL ROLLBACK WORK; if (SQLCODE != 0) { sql_error(); return 1; }else { return 0; } }
执行一个SELECT语句,并查看返回结果(一): int sql_open(const char *DySQL) { EXEC SQL BEGIN DECLARE SECTION; int i, iOutput_count, iOccurs, iType, iLen; short iInd; char sData[1024];//result buffer; char sOutput[64]; char sInput[64]; const char *sDySQL; EXEC SQL END DECLARE SECTION;
执行一个SELECT语句,并查看返回结果(二): SQLCODE = 0; iLen = sizeof(sData); iType = 12;//set type is varchar; sDySQL = DySQL; sprintf(sOutput, "output%p", pContext); sprintf(sInput, "input%p", pContext); EXEC SQL ALLOCATE DESCRIPTOR :sOutput; EXEC SQL ALLOCATE DESCRIPTOR :sInput; EXEC SQL PREPARE S FROM :sDySQL;
执行一个SELECT语句,并查看返回结果(三): if (SQLCODE != 0) { sql_error(); EXEC SQL DEALLOCATE DESCRIPTOR :sInput; EXEC SQL DEALLOCATE DESCRIPTOR :sOutput; return 1; }
执行一个SELECT语句,并查看返回结果(四): EXEC SQL DECLARE C CURSOR FOR S; EXEC SQL OPEN C USING DESCRIPTOR :sInput; /*选择输出区域*/ EXEC SQL DESCRIBE OUTPUT S USING DESCRIPTOR :sOutput; /*取得选择列表的个数*/ EXEC SQL GET DESCRIPTOR :sOutput :iOutput_count = COUNT; for(i=0;i<iOutput_count;i++) { iOccurs = i + 1; EXEC SQL SET DESCRIPTOR :sOutput VALUE :iOccurs TYPE = :iType, LENGTH = :iLen; }
执行一个SELECT语句,并查看返回结果(五): EXEC SQL WHENEVER NOT FOUND DO BREAK; while(1) { /*行数据,输出描述区*/ EXEC SQL FETCH C INTO DESCRIPTOR :sOutput; for(i=0;i < iOutput_count;i++) { iOccurs = i + 1; memset(sData, 0, sizeof(sData)); iInd = 0; EXEC SQL GET DESCRIPTOR :sOutput VALUE :iOccurs :sData = DATA, :iInd = INDICATOR; if (iInd == -1) { printf("%s ", "NULL"); } else { printf("%s ", sData); } } printf(" "); }
执行一个SELECT语句,并查看返回结果(六): EXEC SQL CLOSE C; EXEC SQL DEALLOCATE DESCRIPTOR :sOutput; EXEC SQL DEALLOCATE DESCRIPTOR :sInput; return 0; }
断开连接: int sql_disconnect() { SQLCODE = 0; EXEC SQL ROLLBACK WORK RELEASE; if (SQLCODE != 0) { sql_error(); return 1; }else { return 0; } }
释放相关资源: int sql_free() { SQLCODE = 0; EXEC SQL CONTEXT FREE :pContext; if (SQLCODE != 0) { sql_error(); return 1; }else { return 0; } }
main函数调用的例子: int main() { sql_init(); sql_connect("dbuser1", "dbuser1", "orcl"); sql_open("select * from baidu"); //sql_commit(); sql_disconnect(); sql_free(); return 0; }