数据类型转换
- Oracle外部数据类型中的string是以零结尾的字符串,类似于varchar2类型!
- char在数据不满的时候,后面部分会被填充为空格
- 在SQL语句中的宿主数据类型可以人为的转换为Oracle的外部数据类型,所以我们可以把char [20]转换为string类型,避免产生多余的空格虽然varchar也可以避免空格,但是varchar还要引用里卖弄具体的成员,所以不是很方便,最方便的方法就是转换为string。
转换语法如下:
- 将定义好的宿主变量进行类型转换–操作同一个变量,只不过变量的类型变成了外部数据类型
EXEC SQL VAR host_variable IS type_name[(length)];
char emp_name[11];
EXEC SQL VAR emp_name IS STRING(11);
以后Oracle操作emp_name的时候就当做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);
以后graphics就等价于 VARRAW(4000)类型,可以用它定义其他变量!类似于typedef定义类型别名!只不过是真的产生了新类型(由宿主类型变成了外部数据类型)!
游标
游标是为了操作多行多列时,逐行或随机处理数据而设计的。数组是一次性获取多条数据,但是对于数据条目很多时,使用数组一次性接收所有数据是不合理的!用游标有目的性的获取数据才是明智之举!
普通游标:只能单方向一行一行的检索数据。
滚动游标:可以随机指向数据库表里的数据,可以指向任意一行!
操作步骤:
- 定义游标
EXEC SQL DECLARE emp_cursor CURSOR FOR
select 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;
INTO 后面变量的顺序要和所查询的表的条目里的列名的顺序一致,一般是宿主变量
(After fetch, cursor pointer moves down one line. Use loop for multiple rows)
- EXEC SQL CLOSE emp_cursor;
普通游标综合示例
#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 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 = "scott";
char *passwd = "lzj123529";
char *serverid = "orcl";
int deptno;
dnameType dname; //string 数据类型 //varchar类型 和 char 类型的区别. 与编译选项有关系
short dname_ind;
locType loc;
short loc_ind;
EXEC SQL END DECLARE SECTION;
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");
}
}
int main()
{
int ret = 0;
int i = 0;
EXEC SQL WHENEVER SQLERROR DO sqlerr02();
connet();
//1 定义游标 为某一次查询定义一个游标
EXEC SQL DECLARE c CURSOR FOR
select deptno, dname, loc from dept ;
//2. 打开游标
EXEC SQL OPEN c ;
//3. 提取数据 fetch into
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while(1)
{
EXEC SQL FETCH c INTO :deptno, :dname:dname_ind, :loc:loc_ind;
if (loc_ind == -1)
{
strcpy(loc, "NULL");
}
if (dname_ind == -1)
{
printf("dname is null \t");
}
printf("%d, %s, %s\n", deptno, dname,loc );
}
//4. EXEC SQL CLOSE c;
EXEC SQL CLOSE c;
EXEC SQL COMMIT WORK RELEASE;
printf("return ok...\n");
return ret ;
}
注意EXEC SQL WHENEVER NOT FOUND DO BREAK;的利用技巧
- 演示效果
oracle@lzj:~$ ./array
connect ok...
50, 20name, 中国
10, ACCOUNTING, NEW YORK
20, RESEARCH, DALLAS
30, SALES, NULL
40, OPERATIONS, BOSTON
61, 中国2, 中国
return ok...
滚动游标
定义的时候多了一个SCROLL关键字
在游标变量的前面多了一些表示偏移量的关键字:
关键字 | 说明 |
---|---|
LAST | 最后一行数据 |
FIRST | 第一行数据 |
ABSOLUTE n | 绝对位置的数据:第n条数据 |
RELATIVE n | 相对位置:相对当前游标位置的第n条数据 |
NEXT | 下一条数据 |
PRIOR | 前一条数据 |
#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 = "22";
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 FOR
select deptno, dname, loc from dept;
//2 打开游标 open cursor
EXEC 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 data
EXEC 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");
}
}