一、概述

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++简介相关推荐

  1. linux 进程参数文件 /proc/pid/cmdline 简介

    在proc根目录下,以数字命名的目录表示当前一个运行的进程,目录名为进程的pid.其内的目录和文件给出了一些关于进程的信息. ywx@ywx:/proc/1500$ ls ls: cannot rea ...

  2. linux进程配置异常中断自动重启_Linux系统配置及服务管理 (四)进程管理

    一.进程简介 进程是已启动的可执行程序的运行实例,进程有以下组成部分: • 已分配内存的地址空间: • 安全属性,包括所有权凭据和特权: • 程序代码的一个或多个执行线程: • 进程状态. 程序: 二 ...

  3. 网上linux实验平台,Linux操作系统实验教程

    第一部分 Linux操作系统基本原理. 第1章 Linux操作系统简介 1.1 Linux的渊源和发展简史 1.2 Linux的基本特性 1.3 Linux内核的开发模式与内核版本号 1.4 Linu ...

  4. 不占用系统资源的休眠linux c,Linux-c系统编程

    进程相关的概念 程序和进程 程序:二进制文件.占用磁盘空间 进程:运行着的程序,数据在内存中,占用系统资源,CPU,物理内存() PCB描述进程(进程控制块) 把描述进程的所有信息的那条记录叫做 PC ...

  5. proc文件系统简介及/proc目录介绍

    1. proc文件系统简介 proc文件系统是由内核创建的虚拟文件系统,被内核用来向用户导出信息,通过它可以在Linux内核空间和用户空间之间进行通信. 2. /proc目录介绍 /proc目录下有很 ...

  6. proc文件系统:1.proc文件系统简介

    文章目录 一.proc文件系统简介 1.是个虚拟文件系统 2.作用 3.函数接口 (1)结点 (2)创建目录函数 (3)创建符号链接函数 (4)创建proc文件函数 (5)删除proc节点函数 一.p ...

  7. linux proc 目录清理_Linux下/proc目录简介

    proc简介 在linux的根目录下存在一个/proc目录,/proc文件系统是一种虚拟文件系统,以文件系统目录和文件形式,提供一个指向内核数据结构的接口,通过它能够查看和改变各种系统属性.proc目 ...

  8. linux下/proc目录简介

    1./proc目录概述 Linux 内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构.改变内核设置的机制.proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间.它 ...

  9. 观察内核linux行为,Linux 学习:基于proc观察Linux行为

    内容简介 本篇博文的主要内容是通过/proc文件,对Linux系统管理有一个初步的认识. 在Linux中,proc文件系统提供了一套在用户态检查内核状态和系统特征的机制.proc文件系统将进程的地址空 ...

最新文章

  1. 页面可视化搭建工具前生今世
  2. Longest Y 字符串,货仓选址模型(600)
  3. android webview 模拟器,android – WebView没有填满设备或模拟器的整个屏幕
  4. Android实现简单的检测手机自由落体关闭屏幕
  5. FPGA Verilog实现一个脉冲波形变换
  6. 清华90后博士后26岁已在《科学》发文6篇
  7. qt 5编程入门(第2版)_《C++并发编程实战第2版》第六章:设计基于锁的并发数据结构(1/3)...
  8. 【Android】自定义控件让TextView的drawableLeft与文本一起居中显示
  9. update关联其他表批量更新数据-跨数据库-跨服务器Update时关联表条件更新
  10. VBA_Excel_教程:分枝循环结构
  11. 单片机c指令右移指令_单片机「5」51单片机指令集(2)
  12. lisp 标注螺纹孔_螺纹的标注方法
  13. 简述计算机键盘上shift键的作用,shift键的作用是什么
  14. ubuntu下 端口映射
  15. 安装office时总得到“安装程序包的语言不受系统支持”的提示解决方法
  16. 学习推荐《零起点Python大数据与量化交易》中文PDF+源代码
  17. 南卡小音舱体验评测:CD级音质听感震撼
  18. 论文阅读(Chenyi Chen——【ACCV2016】R-CNN for Small Object Detection)
  19. 两个高斯分布乘积的理论推导
  20. Windows Terminal配置

热门文章

  1. 分销平台传统的宣传流程
  2. 股民误将向日葵当成农业股
  3. 计算机软件在生物学应用,计算机辅助教学软件在生物教学中的应用
  4. 正则表达式:特殊字符之“-”(减号)
  5. 【经验分享】30个使用Python编程的实践、建议和技巧
  6. linux系统能做什么的,Linux系统适合日常使用吗?普通人学Linux能干什么
  7. Smart3D系列教程6之 《案例实战演练3——倾斜数据正射影像及DSM的生产》
  8. 3.19字节懂车帝一面
  9. emoji 原生表情解析成对应表情包png
  10. 住房公积金联名卡密码修改步骤