proc*c/c++简介
一、概述
1. 概念
通过在过程化编程语言C/C++中嵌入SQL语句而开发出的应用程序。在通用编程语言中使用的SQL称为嵌入式SQL。
在SQL标准中定义了多种语言的嵌入式SQL ,各个厂商对嵌入式SQL的具体实现不同。
在C/C++语言中嵌入SQL语句而开发出的应用程序称为Pro*C/C++程序。
目的:使c/c++这种高效率语言成为访问数据库的工具。
嵌入式SQL的载体是宿主语言。
宿主语言 Pro程序
C/C++ Pro*C/C++
FORTRAN Pro*FORTRAN
PASCAL Pro*PASCAL
访问数据库的方法
用SQL*Plus, 它有SQL命令以交互的应用程序访问数据库;
用第四代语言应用开发工具开发的应用程序访问数据库,这些工具有SQL*Froms,QL*Reportwriter,SQL*Menu等;
利用在第三代语言内嵌入的SQL语言或ORACLE库函数调用来访问。
访问oracle数据库的方法
SQLPLUS oracle自带访问数据库工具
JDBC java database connectivity standard
ODBC open database connectivity开放数据库互连
OCI oracle call interface
OCCI oracle c++ call interface
Pro*X Pro*C/C++ Pro*COBOL等
2. 程序结构
Pro*C程序实例
#include <stdio.h>#include <string.h>#include <stdlib.h>#include "sqlca.h"EXEC SQL BEGIN DECLARE SECTION;char username[32];char password[32];char dname[25];EXEC SQL END DECLARE SECTION;EXEC SQL INCLUDE sqlca;void sqlerror();main(){EXEC SQL WHENEVER SQLERROR DO sqlerror();strcpy(username,“haha");strcpy(password, “haha");EXEC SQL CONNECT:username IDENTIFIED BY:password;EXEC SQL select dname into :dname from dept where id=10;printf(“dname:%s \n”, dname);}void sqlerror(){EXEC SQL WHENEVER SQLERROR CONTINUE;printf("\n---- oracle error detected:\n");printf("%.70s\n", sqlca.sqlerrm.sqlerrmc);EXEC SQL ROLLBACK WORK RELEASE;exit(1);}
Pro*C程序结构
Include 头文件 (c/c++ and pro*c/c++)
定义变量
定义函数
main
连结数据库: connect
SQL 操作语句: EXEC SQL …….;
exception handler
断开连结:
EXEC SQL COMMIT / ROLLBACK WORK release
3. 开发流程
需要使用proc将.pc文件预编译为.c文件,再按照.c文件的流程编译.c文件。
例子
编写hello.pc
#include <stdio.h>#include <string.h>#include "sqlca.h"EXEC SQL BEGIN DECLARE SECTION ;char *serverid = "scott/123456@orcl";EXEC SQL END DECLARE SECTION;int main(){int ret = 0;printf("hello...\n");printf("serverid:%s\n", serverid);EXEC SQL connect :serverid;if(sqlca.sqlcode != 0){ret = sqlca.sqlcode;printf("EXEC SQL connect:err, %d\n", ret);return ret;}printf("connect ok\n");return ret;}
使用proc命令proc hello.pc
使用gcc命令
gcc hello.c -I/home/oracle_11/app/oracle/product/11.2.0/db_1/precomp/public -L//home/oracle_11/app/oracle/product/11.2.0/db_1/lib -lclntsh
c++例子
编写c++版的hellocpp.pc
#include <stdio.h>#include <string.h>#include "sqlca.h"using namespace std;EXEC SQL BEGIN DECLARE SECTION ;char *serverid = "scott/123456@orcl";EXEC SQL END DECLARE SECTION;int main(){int ret = 0;cout << "hello...\n" << endl;cout << "serverid:" << serverid << endl;EXEC SQL connect :serverid;if(sqlca.sqlcode != 0){ret = sqlca.sqlcode;printf("EXEC SQL connect:err, %d\n", ret);return ret;}printf("connect ok\n");return ret;}
使用proc编译
proc iname=C:\Users\Administrator\Desktop\hellocpp.pc oname= C:\Users\Administrator\Desktop\hellocpp.cc PARSE=NONE CODE=CPP
使用g++编译
g++ hellocpp.cc -I/home/oracle_11/app/oracle/product/11.2.0/db_1/precomp/public -L//home/oracle_11/app/oracle/product/11.2.0/db_1/lib -lclntsh
二、prc*c/c++基础开发
1. 连接数据库
见上面的例子。
2. 宿主变量和指示器变量
宿主变量是一种pro*c语言变量, 用于在应用程序中和oracle数据库之间传递数据。Pro*C程序中,既可在SQL语句中引用,也可在C语句中引用的变量称为SQL变量。
宿主变量的数据类型
char 单字符
char[n] N个定长字符数组
int 整数
Short 短整数
long 长整数
float 单精度浮点数
double 双精度浮点数
VARCHAR[n] 变长字符串
例子
编写demo1.pc
#include <stdio.h>#include <string.h>#include "sqlca.h"EXEC SQL BEGIN DECLARE SECTION ;char *serverid = "scott/123456@orcl";int tid;char tname[20];char taddress[50];int tid2;char tname2[20];char taddress2[50];EXEC SQL END DECLARE SECTION;int main(){int ret = 0;printf("hello...\n");printf("serverid:%s\n", serverid);EXEC SQL connect :serverid;if(sqlca.sqlcode != 0){ret = sqlca.sqlcode;printf("EXEC SQL connect:err, %d\n", ret);return ret;}printf("connect ok\n");tid = 1;EXEC SQL select tid, tname, taddress into :tid2, :tname2, :taddress2 from t1 where tid=:tid;printf("%d, %s, %s\n", tid, tname, taddress);tid = 100;strcpy(tname, "test1");strcpy(taddress, "beij");EXEC SQL insert into t1 (tid, tname, taddress) values (:tid, :tname, :taddress);EXEC SQL COMMIT;strcpy(taddress, "shangh");EXEC SQL update t1 set taddress=:taddress where tid=:tid;EXEC COMMIT;EXEC SQL delete from t1 where tid=:tid;EXEC SQL COMMIT RELEASE;return ret;}
指示变量(indicator variable)
短整型变量,用于处理数据库的NULL值,监督和管理与其相关联的宿主变量。
引用语法:
:host_variable INDICATOR :indicator_variable
OR
:host_variable:indicator_variable
主要用在输出, 即当宿主变量用于接收数据库的返回数据时.
通过在宿主变量后用指示变量, 检测是否返回了NULL.
-1:数据库表列的值为NULL,指示变量相关联的输出宿主变量值不确定
=0:Oracle将数据库表列值原封不动的赋给指示器变量相关联的输出宿主变量
>0: Oracle将数据库表列值截断后赋给指示器变量相关联的输出宿主变量,指示器变量值为该列值的原始长度
例子:
#include <stdio.h>#include <string.h>#include "sqlca.h"typedef char danmeType[20];typedef char locType[20];EXEC SQL BEGIN DECLARE SECTION;char *serverid = "scott/1234@orcl";int deptno;int dname[20];short dname_ind;char loc[20];short loc_ind;int deptno2;int dname2[20];char loc2[20];EXEC SQL END DECLARE SECTION;int main(){int ret = 0;EXEC SQL connect :serverid;if(sqlca.sqlcode != 0){ret = sqlca.sqlcode;printf("EXEC SQL connect:err, %d\n", ret);return ret;}printf("connect ok\n");deptno2 = 10;EXEC SQL select deptno, dname, loc into :deptno2, :dname2, :loc2:loc_ind from dept where deptno2=:deptno;if(loc_ind == -1){printf("loc2 is null\n");strcpy(loc2, "null");}deptno = 20;strcpy(dname, "sale");strcpy(loc, "bj");printf("%d, %s, %s\n", deptno2, dname2, loc2);loc_ind = -1;EXEC SQL insert into dept (deptno, dname, loc) values (:deptno, :dname, :loc:loc_ind);EXEC SQL COMMIT RELEASE;}
3. oracle数据类型
宿主变量可以被sql语言使用也可以被C语言使用.
C 的数据类型不同于ORACLE的数据类型,在数据传递时有一个数据类型转换的过程。
Oracle数据就是Oracle数据库内部使用的数据类型:
VARCHAR2:变长字符串,最大4000字节
CHAR:定长字符串,最大2000字节
NUMBER(p,s) :数字类型,p精度,s标度
DATE:日期时间数据,7字节
RAW:变长二进制数据,最大2000字节
LONG:大批量数据,最大2G字节
LONG RAW:大二进制数据,最大2G字节
CLOB:大批量字符数据,最大4G
BLOB:大批量二进制数据,最大4G
BFILE:OS文件数据
NCHAR,NVARCHAR2,NCLOB:本地字符集数据
ROWID:伪列——表行物理地址
Oracle外部数据类型是宿主程序所引用的数据类型,在运行Pro*C/C++程序的时候,Oracle会根据需要将宿主变量的数据类型映射成Oracle外部数据类型,在编写Pro*C/C++程序的时候不能直接使用Oracle外部数据类型来定义宿主变量。
VARCHAR2:变长字符串
NUMBER:数字值
INTEGER:有符号整数
FLOAT:浮点数
STRING:以NULL终止的变长字符串
VARNUM:数字值,但包含数字长度
LONG:长字符串
VARCHAR:变长字符串
ROWID:二进制值
DATE:日期
VARRAW:变长二进制
RAW:定长二进制
LONG RAW:定长二进制
UNSIGNED:无符号整数
LONG VARCHAR:变长字符串
LONG VARRAW:变长二进制
CHAR:定长字符
CHARZ:NULL终止定长字符串
CHARF:等价CHAR的字符数据类型
MLSLABEL:操作系统标记
Oracle的外部数据类型与宿主变量的人工类型转换的3中方式:
EXEC SQL VAR host_variable IS type_name[(length)];char emp_name[11];EXEC SQL VAR emp_name IS STRING(11);
用户定义类型等价
EXEC SQL TYPE user_type IS type_name[(length)];typedef struct {short len;char buff[4000];} graphics;EXEC SQL TYPE graphics IS VARRAW(4000);TO_DATE
例子
EXEC SQL BEGIN DECLARE SECTION;EXEC SQL TYPE dnameType is string(20);EXEC SQL TYPE locType is string(20);char *usrname = "scott";char *passwd = "123";char *serverid = "orcl";int deptno;dnameType dname;short dname_ind;locType loc;short loc_ind; EXEC SQL END DECLARE SECTION;
4. oracle通讯区和错误处理机制
SQLCA 是ORACLE提供的两个通信区之一。SQLCA实际上是一个结构变量,其目的是为了诊断错误和事件处理结果。
错误处理机制
当在pro*c/c++应用程序中运行sql语句时,oracle会将最近执行的sql语句的状态信息存储到状态变量sqlcode、sqlstate或sqlca结构中。当sql语句执行成功时,一般情况下不需要进行任何其他处理;当sql语句执行失败时,应用程序应该能够检测到失败信息,并进行适当的处理,以加强应用程序的健壮性。在编写pro*c/c++应用程序时,通过使用whenever语句可以检测并处理sql错误。
EXEC SQL WHENEVER <condition> <action>
其中,conditon用于指定要检测的条件,action用于指定满足特定条件时要执行的操作。
例子:
#include <stdio.h>#include <string.h>#include "sqlca.h"typedef char danmeType[20];typedef char locType[20];EXEC SQL BEGIN DECLARE SECTION;char *serverid = "scott/1234@orcl";int deptno;int dname[20];short dname_ind;char loc[20];short loc_ind;int deptno2;int dname2[20];char loc2[20];EXEC SQL END DECLARE SECTION;void sqlerr(){EXEC SQL WHENEVER SQLERROR CONTINUE;printf("err reason:%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);EXEC SQL ROLLBACK WORK RELEASE;exit(1);}int main(){int ret = 0;EXEC SQL WHENEVER SQLERROR DO sqlerr();EXEC SQL connect :serverid;if(sqlca.sqlcode != 0){ret = sqlca.sqlcode;printf("EXEC SQL connect:err, %d\n", ret);return ret;}printf("connect ok\n");deptno2 = 10;EXEC SQL select deptno, dname, loc into :deptno2, :dname2, :loc2:loc_ind from dept where deptno2=:deptno;if(loc_ind == -1){printf("loc2 is null\n");strcpy(loc2, "null");}deptno = 20;strcpy(dname, "sale");strcpy(loc, "bj");printf("%d, %s, %s\n", deptno2, dname2, loc2);loc_ind = -1;EXEC SQL insert into dept (deptno, dname, loc) values (:deptno, :dname, :loc:loc_ind);EXEC SQL COMMIT RELEASE;}
5. 宿主数组
例子
#include <stdio.h>#include <string.h>#include <stdlib.h>#include "sqlca.h"//连接数据void sqlerr();void sqlerr2();//先定义宿主变量 (SQL变量)EXEC SQL BEGIN DECLARE SECTION ;char * serverid = "scott/tiger@orcl";int deptno[100];char dname[100][20];char loc[100][20];int count;int deptno2[100];varchar dname2[100][20];varchar loc2[100][20];short loc_ind[100];EXEC SQL END DECLARE SECTION ;//sqlerrd[2]SQL语句处理的行数,如果SQL执行失败,则没有定义int main(){int ret = 0, i = 0;int count;printf("hello....\n");EXEC SQL WHENEVER SQLERROR DO sqlerr();EXEC SQL connect :serverid;//EXEC SQL WHENEVER NOT FOUND CONTINUE;EXEC SQL select deptno, dname, loc into :deptno2, :dname2, :loc2:loc_ind from dept ;count= sqlca.sqlerrd[2];printf("count: %d \n", count);for (i=0; i<count; i++){printf("%d, %s, %s\n", deptno2[i], dname2[i].arr, loc2[i].arr);}/*// create + ascreate table dept33as select * from dept where 1=2*/EXEC SQL FOR :count insert into dept33(deptno, dname, loc) values(:deptno2, :dname2, :loc2);EXEC SQL COMMIT RELEASE; //提交事务断开连接return ret; }//错误SQL语言给打印出来void sqlerr02(){char stm[120];size_t sqlfc, stmlen=120;unsigned int ret = 0;printf("func sqlerr02() begin\n");//出错时,可以把错误SQL语言给打印出来EXEC SQL WHENEVER SQLERROR CONTINUE;ret = sqlgls(stm, &stmlen, &sqlfc);/*if (ret != 0){printf("func sqlgls() err, %d \n", ret);return ;}*/printf("中国\n");printf("出错的SQL:%.*s\n", stmlen, stm);printf("出错原因:%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);//printf("出错原因:%.70s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);EXEC SQL ROLLBACK WORK RELEASE;printf("func sqlerr02() end\n");exit(1);}//出错原因void sqlerr(){EXEC SQL WHENEVER SQLERROR CONTINUE; // 下一步printf("err reason:%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);//printf("err reason:%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);EXEC SQL ROLLBACK WORK RELEASE;//exit(1);}
6. 游标
使用游标,操作多行多列时,逐行或随机处理数据。
基本步骤
定义游标
EXEC SQL DECLARE emp_cursor CURSOR FORselect empno,ename,sal from emp where deptno=10;
打开游标
EXEC SQL OPEN emp_cursor ;(Open cursor: put the select results into a memory place, and the cursor pointer points to the first row data.)
提取数据 fetch into
EXEC SQL FETCH emp_cursor INTO :empnum,:name:salary;
/** 在此处理数据处理**/
(After fetch, cursor pointer moves down one line. Use loop for multiple rows)
关闭游标
EXEC SQL CLOSE emp_cursor;
例子
typedef char dnameType[20];typedef char locType[20];EXEC SQL BEGIN DECLARE SECTION;EXEC SQL TYPE dnameType is string(20);EXEC SQL TYPE locType is string(20);char *usrname = "myscott";char *passwd = "1234";char *serverid = "orcl";int deptno;dnameType dname;short dname_ind;locType loc;short loc_ind; EXEC SQL END DECLARE SECTION;int main01(){int ret = 0; int i = 0;EXEC SQL WHENEVER SQLERROR DO sqlerr02();connet();//EXEC SQL WHENEVER NOT FOUND DO nodata();//1 定义游标 declare cursor 在为某一次查询EXEC SQL DECLARE dept_cursor CURSOR FORselect deptno, dname, loc from dept;//2 打开游标 open cursorEXEC SQL OPEN dept_cursor;//3 获取数据 fetch dataEXEC SQL WHENEVER NOT FOUND DO break;while (1){EXEC SQL FETCH dept_cursor INTO :deptno, :dname:dname_ind, :loc:loc_ind;printf("条目数:%d\t", sqlca.sqlerrd[2]);printf("%d\t %s\t %s ", deptno, dname, loc );if (dname_ind == -1){printf("dname is null \t");}if (loc_ind == -1){printf("loc is null \t");}printf("\n");}//4 关闭游标 close dataEXEC SQL CLOSE dept_cursor; EXEC SQL COMMIT WORK RELEASE;printf("return ok...\n");return ret ;}void connect(){int ret = 0;EXEC SQL CONNECT:usrname IDENTIFIED BY:passwd USING:serverid;if(sqlca.sqlcode != 0){ret = sqlca.sqlcode;printf("sqlca.sqlcode err:%d\n", ret);return ;}else{printf("connect ok ... \n");}}
滚动游标的例子
#include <stdio.h>#include <string.h>#include <stdlib.h>#include "sqlca.h"extern sqlgls(char * , size_t *, size_t * );extern sqlglmt(void *,char *,size_t *,size_t *);void connet();void sqlerr02();void sqlerr02(){char stm[120];size_t sqlfc, stmlen=120;unsigned int ret = 0;//出错时,可以把错误SQL语言给打印出来EXEC SQL WHENEVER SQLERROR CONTINUE;ret = sqlgls(stm, &stmlen, &sqlfc); printf("出错的SQL:%.*s\n", stmlen, stm);printf("出错原因:%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);//printf("出错原因:%.70s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);EXEC SQL ROLLBACK WORK RELEASE;exit(1);}void nodata(){int ret = 0;printf("没有发现数据\n");if (sqlca.sqlcode != 0){ret = sqlca.sqlcode;printf("sqlca.sqlcode: err:%d \n", sqlca.sqlcode);return ;}}typedef char dnameType[20];typedef char locType[20];EXEC SQL BEGIN DECLARE SECTION;EXEC SQL TYPE dnameType is string(20);EXEC SQL TYPE locType is string(20);char *usrname = "myscott";char *passwd = "1234";char *serverid = "orcl";int deptno;dnameType dname; //string 数据类型 short dname_ind;locType loc;short loc_ind; EXEC SQL END DECLARE SECTION;int main(){int ret = 0; int i = 0;EXEC SQL WHENEVER SQLERROR DO sqlerr02();connet();//EXEC SQL WHENEVER NOT FOUND DO nodata();//1 定义游标 declare cursor 在为某一次查询EXEC SQL DECLARE dept_cursor SCROLL CURSOR FORselect deptno, dname, loc from dept;//2 打开游标 open cursorEXEC SQL OPEN dept_cursor;//3 获取数据 fetch data//while (1){//EXEC SQL WHENEVER NOT FOUND DO break;//查询最后一条数据EXEC SQL FETCH LAST dept_cursor INTO :deptno, :dname:dname_ind, :loc:loc_ind;//printf("条目数:%d\t", sqlca.sqlerrd[2]);printf("%d\t %s\t %s \n", deptno, dname, loc );//查询第一条数据EXEC SQL FETCH FIRST dept_cursor INTO :deptno, :dname:dname_ind, :loc:loc_ind;//printf("条目数:%d\t", sqlca.sqlerrd[2]);printf("%d\t %s\t %s \n", deptno, dname, loc );//查询第3条数据EXEC SQL FETCH ABSOLUTE 3 dept_cursor INTO :deptno, :dname:dname_ind, :loc:loc_ind;//printf("条目数:%d\t", sqlca.sqlerrd[2]);printf("%d\t %s\t %s \n", deptno, dname, loc );//查询相对第3条数据 也就是第6条EXEC SQL FETCH RELATIVE 3 dept_cursor INTO :deptno, :dname:dname_ind, :loc:loc_ind;//printf("条目数:%d\t", sqlca.sqlerrd[2]);printf("%d\t %s\t %s \n", deptno, dname, loc );//查询下一条EXEC SQL FETCH NEXT dept_cursor INTO :deptno, :dname:dname_ind, :loc:loc_ind;//printf("条目数:%d\t", sqlca.sqlerrd[2]);printf("%d\t %s\t %s \n", deptno, dname, loc );//查询前一条EXEC SQL FETCH PRIOR dept_cursor INTO :deptno, :dname:dname_ind, :loc:loc_ind;//printf("条目数:%d\t", sqlca.sqlerrd[2]);printf("%d\t %s\t %s \n", deptno, dname, loc );}//4 关闭游标 close dataEXEC SQL CLOSE dept_cursor; EXEC SQL COMMIT WORK RELEASE;printf("return ok...\n");return ret ;}void connet(){int ret = 0;//连接数据库EXEC SQL CONNECT:usrname IDENTIFIED BY:passwd USING:serverid ;if (sqlca.sqlcode != 0){ret = sqlca.sqlcode;printf("sqlca.sqlcode: err:%d \n", sqlca.sqlcode);return ;}else{printf("connect ok...\n");}}
三、pro*c/c++动态sql
1. 概念
动态SQL是指在运行pro*c/c++应用程序时,动态输入的SQL语句。
目的:加强应用程序的功能和灵活性。
比较静态SQL和动态SQL:
静态SQL ---- 在编写应用程序时,使用EXEC SQL关键字直接嵌入的SQL语句;在proc编译应用程序生成c语言的时,都已经确定
动态SQL ---- 在运行应用程序时,由用户动态输入的SQL语句。
使用动态SQL语句的情形:
SQL语句的文本(命令,子句等)不确定
宿主变量个数不确定
宿主变量的数据类型不确定
引用的数据库对象(列,表等)不确定
2. 动态sql方法1
语法:EXEC SQL EXECUTE IMMEDIATE :host_string
host_string 字符串
限制性,要求是非select语言,无宿主变量。
例子
int main (){int ret = 0; int i = 0;char choosechar;memset(mySql, 0, sizeof(mySql));pSql = NULL;EXEC SQL WHENEVER SQLERROR DO sqlerr02();connet();pSql = mySql;//循环处理sql语言for(;;){printf("\nplease enter sql(not select ): ");gets(mySql);//scanf("%s", mySql); --空格截断printf("mysql:%s\n", mySql);printf("任意键继续....\n");getchar();EXEC SQL EXECUTE IMMEDIATE :pSql;EXEC SQL COMMIT;printf("继续执行吗?\n");scanf("%c", &choosechar);fflush(stdin);if (choosechar=='n' || choosechar=='N'){break;}}EXEC SQL COMMIT WORK RELEASE;printf("return ok...\n");return ret ;}
3. 动态sql2
使用PREPARE命令准备SQL语句
EXEC SQL PREPARE statement_name FROM :host_string;
statement_name: 标识符
host_string:含SQL语句的字符串
使用EXECUTE命令执行SQL语句
EXEC SQL EXECUTE statement_name [USING :host_variable]
如果SQL语句要通过宿主变量赋值,输入SQL语句时要用占位符
例子
int main02(){int ret = 0; int i = 0;char choosechar;memset(mySql, 0, sizeof(mySql));pSql = NULL;EXEC SQL WHENEVER SQLERROR DO sqlerr02();connet();pSql = mySql;//循环处理sql语言for(;;){printf("\n请输入要更新部门编号 ");scanf("%d", &deptno);printf("\n请输入要新loc值 ");scanf("%s", loc);//准备动态sqlEXEC SQL PREPARE my_pre_sql FROM 'update dept set loc = :a where deptno = :b';//执行动态sqlEXEC SQL EXECUTE my_pre_sql USING :loc, :deptno;EXEC SQL COMMIT;printf("\n 按任意键继续? ");getchar();printf("\n退出键入n, 其他继续? ");scanf("%c", &choosechar);fflush(stdin);if (choosechar=='n' || choosechar=='N'){break;}}EXEC SQL COMMIT WORK RELEASE;printf("return ok...\n");return ret ;}
4. 动态sql3
使用PREPARE命令准备SQL语句
EXEC SQL PREPARE statement_name FROM :host_string;
statement_name: 标识符,
host_string:含SQL语句的字符串
使用DECLARE命令定义游标
EXEC SQL DECLARE cursor_name CURSOR FOR statement_name;EXEC SQL OPEN cursor_name [using host_variable_list]EXEC SQL FETCH cursor_name INTO host_variable_listEXEC SQL CLOSE cursor_name
例子
//可以结合游标一块使用int main(){int ret = 0; int i = 0;char choosechar;memset(mySql, 0, sizeof(mySql));pSql = NULL;EXEC SQL WHENEVER SQLERROR DO sqlerr02();connet();//EXEC SQL WHENEVER NOT FOUND DO nodata();//循环处理sql语言for(;;){printf("\n请输入部门编号 ");scanf("%d", &deptno);//准备动态sqlEXEC SQL PREPARE my_pre_sql3 FROM 'select deptno, dname, loc from dept where deptno > :a';//定义游标EXEC SQL DECLARE c1 CURSOR FOR my_pre_sql3;//打开游标EXEC SQL OPEN c1 USING :deptno;//提取数据EXEC SQL WHENEVER NOT FOUND DO break;for (;;){EXEC SQL FETCH c1 INTO :deptno, :dname,:loc:loc_ind;printf("%d\t %s\t %s \n", deptno, dname, loc);}EXEC SQL CLOSE c1;EXEC SQL COMMIT;printf("\n 按任意键继续? ");getchar();printf("\n键入 n 退出, 其他继续? ");scanf("%c", &choosechar);fflush(stdin);if (choosechar=='n' || choosechar=='N'){break;}}EXEC SQL COMMIT WORK RELEASE;printf("return ok...\n");return ret ;}
5. 动态sql4
既适用于SELECT语句,也适用于非SELECT语句,但是,它与前面的方法相比有两个突出的不同点:
方法4的动态SQL语句不但包含选择表项或虚拟输入宿主变量,而且它们的个数或数据类型在编译时还不知道
在其它方法中,ORACLE和C之间的数据类型转换是自动实现的。而在方法4中,由于动态语句中的宿主变量个数和类型在编译时还不知道,因此不能实现自动转换,必须由程序来控制数据类型之间的转换
提供信息
选择表项和实输入宿主变量的个数
每一个选择表项和实输入宿主变量的成年高度
每一个选择表项和实输入宿主变量的数据类型
每一个输出宿主变量和实输入宿主变量的内存单元地址
SQLDA
为了保存执行动态SQL语句所需要的信息,系统提供一个称之为SQL描述区的程序数据结构。把ORACLE所需要的全部有关选择表项或虚拟输入宿主变量的信息,除了值和名字外,都存储在SQLDA中
SQLDA中所包含的信息主要通过以下三种方法写入:
sqlald()函数:在分配描述区和缓冲区的同时,还把SLI或P的名字在缓冲区中的地址和长度写入SQLDA中
应用程序:通过程序把SLI或BV值的缓冲区地址、长度既数据类型写入SQLDA
DESCRIBE语句:检查每一个选择表项,确定它的名字、数据类型、约束、长度、定标和精度,然后把这方面的信息存储在选择SQLDA和输出缓冲区中,以供用户使用
proc*c/c++简介相关推荐
- linux 进程参数文件 /proc/pid/cmdline 简介
在proc根目录下,以数字命名的目录表示当前一个运行的进程,目录名为进程的pid.其内的目录和文件给出了一些关于进程的信息. ywx@ywx:/proc/1500$ ls ls: cannot rea ...
- linux进程配置异常中断自动重启_Linux系统配置及服务管理 (四)进程管理
一.进程简介 进程是已启动的可执行程序的运行实例,进程有以下组成部分: • 已分配内存的地址空间: • 安全属性,包括所有权凭据和特权: • 程序代码的一个或多个执行线程: • 进程状态. 程序: 二 ...
- 网上linux实验平台,Linux操作系统实验教程
第一部分 Linux操作系统基本原理. 第1章 Linux操作系统简介 1.1 Linux的渊源和发展简史 1.2 Linux的基本特性 1.3 Linux内核的开发模式与内核版本号 1.4 Linu ...
- 不占用系统资源的休眠linux c,Linux-c系统编程
进程相关的概念 程序和进程 程序:二进制文件.占用磁盘空间 进程:运行着的程序,数据在内存中,占用系统资源,CPU,物理内存() PCB描述进程(进程控制块) 把描述进程的所有信息的那条记录叫做 PC ...
- proc文件系统简介及/proc目录介绍
1. proc文件系统简介 proc文件系统是由内核创建的虚拟文件系统,被内核用来向用户导出信息,通过它可以在Linux内核空间和用户空间之间进行通信. 2. /proc目录介绍 /proc目录下有很 ...
- proc文件系统:1.proc文件系统简介
文章目录 一.proc文件系统简介 1.是个虚拟文件系统 2.作用 3.函数接口 (1)结点 (2)创建目录函数 (3)创建符号链接函数 (4)创建proc文件函数 (5)删除proc节点函数 一.p ...
- linux proc 目录清理_Linux下/proc目录简介
proc简介 在linux的根目录下存在一个/proc目录,/proc文件系统是一种虚拟文件系统,以文件系统目录和文件形式,提供一个指向内核数据结构的接口,通过它能够查看和改变各种系统属性.proc目 ...
- linux下/proc目录简介
1./proc目录概述 Linux 内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构.改变内核设置的机制.proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间.它 ...
- 观察内核linux行为,Linux 学习:基于proc观察Linux行为
内容简介 本篇博文的主要内容是通过/proc文件,对Linux系统管理有一个初步的认识. 在Linux中,proc文件系统提供了一套在用户态检查内核状态和系统特征的机制.proc文件系统将进程的地址空 ...
最新文章
- 页面可视化搭建工具前生今世
- Longest Y 字符串,货仓选址模型(600)
- android webview 模拟器,android – WebView没有填满设备或模拟器的整个屏幕
- Android实现简单的检测手机自由落体关闭屏幕
- FPGA Verilog实现一个脉冲波形变换
- 清华90后博士后26岁已在《科学》发文6篇
- qt 5编程入门(第2版)_《C++并发编程实战第2版》第六章:设计基于锁的并发数据结构(1/3)...
- 【Android】自定义控件让TextView的drawableLeft与文本一起居中显示
- update关联其他表批量更新数据-跨数据库-跨服务器Update时关联表条件更新
- VBA_Excel_教程:分枝循环结构
- 单片机c指令右移指令_单片机「5」51单片机指令集(2)
- lisp 标注螺纹孔_螺纹的标注方法
- 简述计算机键盘上shift键的作用,shift键的作用是什么
- ubuntu下 端口映射
- 安装office时总得到“安装程序包的语言不受系统支持”的提示解决方法
- 学习推荐《零起点Python大数据与量化交易》中文PDF+源代码
- 南卡小音舱体验评测:CD级音质听感震撼
- 论文阅读(Chenyi Chen——【ACCV2016】R-CNN for Small Object Detection)
- 两个高斯分布乘积的理论推导
- Windows Terminal配置