ProCC+++编程.docx
- 文档编号:12358092
- 上传时间:2023-04-18
- 格式:DOCX
- 页数:19
- 大小:48.70KB
ProCC+++编程.docx
《ProCC+++编程.docx》由会员分享,可在线阅读,更多相关《ProCC+++编程.docx(19页珍藏版)》请在冰豆网上搜索。
ProCC+++编程
Pro*C/C++编程
一、Pro*C/C++简介
1.1、Pro*C/C++是什么
为了用户开发Oracle应用程序,Oracle提供了一套Oracle调用规范,即OracleCallInterface(OCI),但是比较难以掌握使用,对于熟悉C/C++的用户要编写Oracle应用程序,还需要花很多时间去研究OCI,因此Oracle推出了一个在C/C++代码中直接嵌入SQL的方法,然后通过Oracle提供的预编译程序,编译成SQLLIB的调用,这就是Pro*C/C++。
注意,SQLLIB与OCI是不同的,SQLLIB主要是保含一系列函数的Oracle应用程序运行库,用于应用程序执行或预编译时调用,其本身并不是Oracle标准接口API,随着Oracle版本的变化SQLLIB的函数调用格式、用法、参数等也有可能变化。
如果一个项目中需要一个比较通用的、平台一致性好的、不随数据库版本变化而变化的一系列封装函数,最好的建议是使用OracleCallInterface(OCI)进行标准C语言的编程处理。
1.2、Pro*C/C++处理流程
C/C++源代码=⇒源代码中嵌入SQL=⇒通过Pro*C预编译命令产生新的源代码
=⇒通过正常的C/C++编译器编译连接应用程序=⇒运行应用程序
二、Pro*C/C++GCC环境配置
2.1、Pro*C/C++预编译环境
当您安装Oracle数据库产品的时候,Pro*C/C++的预编译环境缺省就为我们安装好了,我们这里以安装Oracle10G版本为例.在Oracle_Home的Bin目录下,您可以找到预编译程序proc.exe,这个就是用来预编译您有在C/C++代码中嵌入SQL的文件的.该编译程序用到了Oracle_Home下的precomp\public目录中的.h头文件,在正真编译生成可执行文件时又会用到precomp\lib的一个.lib库文件.
我们进入command窗口,看看proc编译命名的参数:
Pro*C/C++编译命令参数(10G)
C:
\oracle\product\10.2.0\db_2\BIN>proc
Pro*C/C++:
Release10.2.0.1.0-ProductiononMonFeb2316:
22:
292009
Copyright(c)1982,2005,Oracle.Allrightsreserved.
Systemdefaultoptionvaluestakenfrom:
C:
\oracle\product\10.2.0\db_2\precomp\admin\pcscfg.cfg
OptionNameCurrentValueDescription
-------------------------------------------------------------------------------
auto_connectnoAllowautomaticconnectiontoops$account
char_mapcharzMappingofcharacterarraysandstrings
close_on_commitnoCloseallcursorsonCOMMIT
cmax100CMAXValueforconnectionpool
cmin2CMINValueforconnectionpool
cincr1CINCRValueforconnectionpool
ctimeout0CTIMEOUTValueforconnectionpool
cnowait0CNOWAITValueforconnectionpool
codecppThetypeofcodetobegenerated
comp_charsetmulti_byteThecharactersettypetheCcompilersupports
configdefaultOverridesystemconfigurationfilewithanother
cpoolnoSupportconnectionpooling
cpp_suffixccOverridethedefaultC++filenamesuffix
dbmsnativev6/v7/v8compatibilitymode
def_sqlcodenoGenerate'#defineSQLCODEsqlca.sqlcode'macro
define*none*Defineapreprocessorsymbol
durationtransactionSetpindurationforobjectsinthecache
dynamicoracleSpecifyOracleorANSIDynamicSQLSemantics
errorsyesWhethererrormessagesaresenttotheterminal
errtype*none*Nameofthelistfileforintypefileerrors
eventsnoSupportpublish-subscribeeventnotifications
fipsnoneFIPSflaggingofANSInoncompliantusage
header*none*SpecifyfileextensionforPrecompiledHeaders
hold_cursornoControlholdingofcursorsinthecursorcache
iname*none*Thenameoftheinputfile
include*none*Directorypathsforincludedfiles
intype*none*Thenameoftheinputfilefortypeinformation
linesnoAdd#linedirectivestothegeneratedcode
lname*none*Overridedefaultlistfilename
ltypeshortTheamountofdatageneratedinthelistfile
maxliteral1024Maximumlengthofageneratedstringliteral
maxopencursors10Maximumnumberofcachedopencursors
modeoracleCodeconformancetoOracleorANSIrules
native_typesnoSupportfornativefloat/double
nls_char*none*SpecifyNationalLanguagecharactervariables
nls_localnoControlhowNLScharactersemanticsaredone
objectsyesSupportobjecttypes
oname*none*Thenameoftheoutputfile
oracanoControltheuseoftheORACA
pagelen80Thepagelengthofthelistfile
parsenoneControlwhichnon-SQLcodeisparsed
prefetch1Numberofrowspre-fetchedatcursorOPENtime
release_cursornoControlreleaseofcursorsfromcursorcache
select_erroryesControlflaggingofselecterrors
sqlcheckSEMANTICSAmountofcompile-timeSQLchecking
sys_include*none*Directorywheresystemheaderfilesarefound
threadsnoIndicatesamulti-threadedapplication
type_codeoracleUseOracleorANSItypecodesforDynamicSQL
unsafe_nullnoAllowaNULLfetchwithoutindicatorvariable
userid*none*Ausername/password[@dbname]connectstring
utf16_charsetnchar_charsetThecharactersetformusedbyUTF16variables
varcharnoAllowtheuseofimplicitvarcharstructures
versionrecentWhichversionofanobjectistobereturned
win32_threadsnoSupportwindowsdefaultlocalthreading
PCC-F-02135,CMD-LINE:
Useraskedforhelp
这些命令参数选项,除了直接在命令行参数中指定外,您也可以通过precomp\admin\psccfg.cfg文件中进行指定,下面是一个样例:
ltype=short
code=cpp
cpp_suffix=cc
parse=none
SQLCHECK=SEMANTICS
这里我们介绍其中的三个参数:
∙code=cpp这个参数表明我们通过proc预编译命令产生的代码文件是符合C++规范的,如果您是在标准C环境中使用,那么您可以指定code=ansi_c
∙cpp_suffix=cc这个参数让proc命令产生的文件以.cc作为文件扩展名
∙SQLCHECK=SEMANTICS这个参数用于指示在预编译的时候是否要检查嵌入的SQL的语法,您可以设置NONE表示不检查(10G中中已经不再支持这个值了,至少设置为SYNTAX),SEMANTICS表示检查语义(也就是检查数据库表名,列名是否存在等)
2.2、GCC编译器
在Windows环境中,您可以选择使用微软的VC编译器,或者Bland公司的BC编译器.我们这里使用GCC1)编译器,GCC编译器的安装可以直接从http:
//gcc.gnu.org这里下载,最新提供一个在Windows下快速安装的工具程序.这里我们采用了Dev-CPP的开发环境,这个开发环境中包含了GCC,下载地址见
三、开始编写第一个Pro*C++代码
3.1、第一个Pro*C++代码
本文中涉及到的C++知识不做过多介绍,已经超出了本文范围.
编写一个Oracle登陆程序(我们这里使用C++代码,当然您也可以使用标准C代码):
1:
usingnamespacestd;
2:
#include
3:
#include"sqlca.h"//SQLComunicationArea
4:
5:
EXECSQLBEGINDECLARESECTION;
6:
char*uid="scott/tiger@orcl10g";
7:
EXECSQLENDDECLARESECTION;
8:
9:
intmain()
10:
{
11:
EXECSQLCONNECT:
uid;
12:
if(sqlca.sqlcode!
=0)
13:
cout< 14: else 15: cout<<"Success."< 16: EXECSQLCOMMITWORKRELEASE; 17: } 第5,7行代码表示要定义SQL宿主变量,这里边的变量的定义方式依照C++中的方式定义.这些变量除了能够在正常的C++代码中使用外,也能使用在嵌入的SQL语句中,因此被成为宿主变量 第6行就申明了一个SQL宿主变量 第11行为连接数据库的指令. 第12行判断SQL通讯区变量sqlca中的信息,以检查sql语句执行是否成功,这里检查是否连接成功,成功执行sqlca.sqlcode值为0,当有错误发生时,sqlca.sqlerrm这个子结构保存了相应的错误讯息. 第16行为提交工作并释放资源(也即断开连接). 我们把这个文件保存在C: \proc目录下,命名为myfirst.pc(通常我们编写的Pro*C程序以.pc结尾) 3.2、Pro*C++代码预编译 首先设置预编译命令的路径,然后再行编译 C: \>setORACLE_HOME=C: \oracle\product\10.2.0\db_2 C: \>setpath=%ORACLE_HOME%\bin C: \>cdproc C: \proc>dir/b myfirst.pc C: \proc>procmyfirst.pc Pro*C/C++: Release10.2.0.1.0-ProductiononWedFeb2513: 58: 522009 Copyright(c)1982,2005,Oracle.Allrightsreserved. Systemdefaultoptionvaluestakenfrom: C: \oracle\product\10.2.0\db_2\precomp\admin\pcscfg.cfg C: \proc>dir/b myfirst.cc myfirst.lis myfirst.pc C: \proc> 以上已经与编译成功,我们可以看到新产生了myfirst.cc文件,这个文件就是将嵌入的SQL指令预编译成为标准的ORACLE库函数调用后的文件.您可以查看该文件内容. 3.3、GCC编译 在进行预编译产生正常的C++代码文件后,接下来,我们只需要用C++编译器编译这个.cc文件即可得到我们的可执行文件.我们首先需要设置一下Path,以便找到我们的编译器,我的gcc编译器在c: \Dev-Cpp\bin目录下,由于这里使用的是C++的编程,所以我使用g++编译命令 C: \proc>setpath=C: \Dev-Cpp\bin;%path% C: \proc>g++myfirst.cc myfirst.cc: 145: 19: sqlca.h: Nosuchfileordirectory myfirst.cc: Infunction`intmain()': myfirst.cc: 167: error: `sqlca'undeclared(firstusethisfunction) myfirst.cc: 167: error: (Eachundeclaredidentifierisreportedonlyonceforeachfunctionitappearsin.) 这里出错了,因为sqlca这个结构变量没有找到,实际上是没有找到sqlca.h这个头文件,这个头文件在%ORACLE_HOME%\precomp\public目录下,因此我们通过命令行指定这个位置: C: \proc>g++myfirst.cc-I%ORACLE_HOME%\precomp\public C: \DOCUME~1\nyfor\LOCALS~1\Temp/ccgLbaaa.o(.text+0x2b9): myfirst.cc: undefinedreferenceto`sqlcxt' collect2: ldreturned1exitstatus C: \proc> 依然有错误,提示找不到sqlcxt的引用,这个是在链接的时候发生的错误,链接时需要一个Oracle库文件,这个库文件位置在%ORACLE_HOME%\precomp\lib目录中,文件名为: orasql10.lib,Oracle9i的文件名为orasql9.lib 我们指定库文件路径及库文件后重新编译: C: \proc>g++myfirst.cc-I%ORACLE_HOME%\precomp\public-L%ORACLE_HOME%\precomp\LIB-lorasql10 C: \proc>dir/b a.exe myfirst.cc myfirst.lis myfirst.pc C: \proc> 至此,我们成功生成了一个可执行文件a.exe,这个文件可以用来测试登陆. 3.4、最后测试 当我们生成好了可执行文件后,我们开始测试, C: \proc>a Success. 当我们把OracleListener停掉后再行测试 C: \proc>a ORA-12170: TNS: Connecttimeoutoccurred 四、复杂一些的Pro*C/C++代码 4.1、代码部分 这里我们直接在代码中编写注释,以阐释Pro*C/C++中的一些基本指令的用法 usingnamespacestd; #include #include"sqlca.h"//引入SQL通讯区 //以下申明一个宿主变量,这是一个全局的变量,这个变量在C代码中和正常的变量一样使用, //在嵌入SQL语句中,在变量名前追加冒号: 来引用该变量. EXECSQLBEGINDECLARESECTION; //只有包含在这之间申明的变量才能用于嵌入SQL代码中 char*uid="scott/tiger@//192.168.8.35: 1522/orcl10"; EXECSQLENDDECLARESECTION; //这里申明了一个函数,后面会做说明,代码实现在最后 voidsql_error(); intmain() { /* 这条指令指示嵌入SQL执行发生错误的时候(不包含NO_DATA_FOUND例外)转向执行的C函数 这个指令还有其它一些语法: EXECSQLWHENEVERSQLERRORCONTINUE;继续执行下一条语句 EXECSQLWHENEVERSQLERRORSTOP;停止应用程序的执行 EXECSQLWHENEVERSQLERRORGOTOlabel;跳转到指定的标号处运行 初始状态为CONTINUE */ EXECSQLWHENEVERSQLERRORDOsql_error(); /* 这条指令连接数据库,常用的连接方法有两种: 一是将用户名和密码存放在两个宿主变量中,采用IDENTIFIEDBY子句: EXECSQLCONNECT: usernameIDENTIFIEDBY: password; 一是将用户名和密码按照“username/password”方式(在用户名和密码中用反斜线做分隔的字符串)存放在一个宿主变量中: EXECSQLCONNECT: usernameandpwd; */ EXECSQLCONNECT: uid; cout<<"DatabaseConnected....."< EXECSQLWHENEVERSQLERRORCONTINUE; //下面这条指令是执行一条本机动态SQL语句,语法和PL/SQL中类似 EXECSQLEXECUTEIMMEDIATE'droptablet_emp'; //前面代码当SQL执行发生错误时设置的CONTINUE,我们在下一条语句检查执行结果 if(sqlca.sqlcode==0)//sqlcode为0表示执行成功. { cout<<"TableT_EMPdroped."< } EXECSQLWHENEVERSQLERRORDOsql_error(); //以下是嵌入的普通的DDL语句,执行完后我们没有检测sqlca.sqlcode, //是因为前面我们设置了出错时进行捕获并执行sql_error()函数 //我们在sql_error函数中进行错误处理. EXECSQLcreatetablet_empasselectempno,ename,salfromempwhere1=0; cout<<"TableT_EMPcreated."< /* 下面在main函数内申明SQL宿主变量,这里的就是局部变量了,只能用在函数main内部以下申明了一些数组变量,供我们用来存储查询语句返回的多行数据,在PL/SQL中我们也曾使用bulkcollectinto子句来批量fetch数据;当然我们也可以不定义数组,而定义单个变量,这样每次就只能获取一条数据. */ EXECSQLBEGINDECLARESECTION; intempno[5];//存放EMPNO字段 charename[5][11]; /*存放ENAME字段,因为在C中字符串是要以'\0'结尾的,所以比我们在DB中定义的10个字节的长度要多定义一个字节,这点要记住了.*/ floatsal[5];//存放SAL字段 /*下面这个数组定义的用途做个描述: 在Oracle的数据值中,有NULL这样一种特殊的值,而在C中并没有这种值,为了表明从Oracle中获取的值是否为NULL,特别定义了一个指示变量(Indicator),在数据返回过程中,通过设置这个指示器变量,以让应用程序知道这个值是否为NULL值,具体用法是将这个指示器变量直接跟在变量后面,数据返回后检查指示器,如果为-1表示值为NULL;为0表
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ProCC 编程