首页 > 代码库 > 数据库编程4 Oracle Pro*C/C++开发
数据库编程4 Oracle Pro*C/C++开发
【本文谢绝转载原文来自http://990487026.blog.51cto.com】
1,上次难点复习 1 求所有部门的平均奖金 2 求各部门的平均薪水 3 求各部门每个工种的平均薪水 4 求各部门每个工种大于2000的平均薪水 5 求10号部门的平均工资(2种写法) 6 创建一个学生表 7 并向表中插入一条数据 8 列出不是管理层的员工: 9 工资最高前10名的员工信息(rownum是一个属性值) 10 找到各部门大于本部门平均薪水的员工: 11 创建索引 Linux 环境 Oracle Pro*C Oracle 编程: 官方文档 Linux 下Oracle数据库的环境部署 配置proc编译器 配置vim 为pc文件高亮 Proc*C/C++编译配置 Oracle数据类型 proc小试身手 C语言方式:SQL 内嵌语法: C++方式,SQL 内嵌语法,proc编译c++需要配置一下 Pro*C 编程:insert into 向数据库插入数据: Pro*C 编程:update 向数据库更新数据: Pro*C 编程:select从数据库查数据:之char数据类型 Pro*C varchar 数据类型,自动去除占位的空格 Pro*C string数据类型,自动去除占位的空格 NULL问题,1,插入数据时,字段填NULL NULL问题,2,获取数据时,判断是否为NULL Pro*C/C++ 编程,向Oracle 插入中文 先把Linux,Oracle,Sqlplus设置为UTF8 Oracle 通讯区 和错误处理: 游标的官方文档 游标与数组:查询多条记录,全部插入一张表中 用普通游标提取数据,一行一行的获取数据,就像单向链表 用滚动游标提取数据,可查询指定任意行数据:指哪儿打哪儿 [难点]动态SQL,1,只能使用非select语法 [难点]动态SQL,2,非查询语言, 带固定数量的宿主变量 [难点]动态SQL,3 处理选择列表项(select查询出来的结果列数固定) [难点]动态SQL4,具备完整select 语法 ANSI方法 [难点]动态SQL4,具备完整select 语法Oracle官方方法
复习
1 求所有部门的平均奖金
SQL> select avg(comm) from emp; AVG(COMM) ---------- 550 SQL> select avg(nvl(comm,0)) from emp; AVG(NVL(COMM,0)) ---------------- 115.789474
2 求各部门的平均薪水
SQL> select deptno, avg(sal) from emp group by deptno; DEPTNO AVG(SAL) ---------- ---------- 30 1566.66667 20 3839.28571 10 4187.5
3 求各部门每个工种的平均薪水
SQL> select deptno, job, avg(sal) from emp group by deptno, job; DEPTNO JOB AVG(SAL) ---------- --------- ---------- 20 CLERK 950 30 SALESMAN 1400 20 MANAGER 2975 30 CLERK 950 10 PRESIDENT 5000 20 clerk 8000 30 MANAGER 2850 10 CLERK 1300 20 10 MANAGER 2450 20 ANALYST 3000 10 8000 12 rows selected.
4 求各部门每个工种大于2000的平均薪水
SQL> select deptno, job, avg(sal) from emp group by deptno, job having avg(sal) >2000; DEPTNO JOB AVG(SAL) ---------- --------- ---------- 20 MANAGER 2975 10 PRESIDENT 5000 20 clerk 8000 30 MANAGER 2850 10 MANAGER 2450 20 ANALYST 3000 10 8000 7 rows selected.
5 求10号部门的平均工资(2种写法)
1:
SQL> select deptno,avg(sal) from emp group by deptno having deptno=10; DEPTNO AVG(SAL) ---------- ---------- 10 4187.5
2:
SQL> select deptno,avg(sal) from emp where deptno=10 group by deptno; DEPTNO AVG(SAL) ---------- ---------- 10 4187.5
6 创建一个学生表
sid sname email sex age SQL> create table studet (sid number(2) primary key, sname varchar2(50) not null,email varchar2(50), sex varchar2(1),age number(2)); Table created. SQL> desc studet; Name Null? Type ------------------------- -------- ----------------------- SID NOT NULL NUMBER(2) SNAME NOT NULL VARCHAR2(14) EMAIL VARCHAR2(20) SEX VARCHAR2(1) AGE NUMBER(2)
7 并向表中插入一条数据
SQL> insert into studet values(10,‘鲁智深‘,‘Linux‘,‘m‘,20); 1 row created.
8 列出不是管理层的员工:
SQL> select * from emp where empno not in (select mgr from emp where mgr is not null); EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- --------- ---------- ---------- ---------- 1 tom_abc 8000 10 2 aaa clerk 7092 17-DEC-80 8000 20 3 abc 20 4 aaa clerk 7092 26-AUG-16 8000 20 5 chunli 20 7369 SMITH CLERK 7902 17-DEC-80 800 20 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 7900 JAMES CLERK 7698 03-DEC-81 950 30 7934 MILLER CLERK 7782 23-JAN-82 1300 10
9,显示工资最高前10名的员工信息(rownum是一个属性值):
SQL> select * from (select * from emp order by sal desc nulls last) where rownum <= 10; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- --------- ---------- ---------- ---------- 1 tom_abc 8000 10 4 aaa clerk 7092 26-AUG-16 8000 20 2 aaa clerk 7092 17-DEC-80 8000 20 7839 KING PRESIDENT 17-NOV-81 5000 10 7788 SCOTT ANALYST 7566 19-APR-87 3000 20 7902 FORD ANALYST 7566 03-DEC-81 3000 20 7566 JONES MANAGER 7839 02-APR-81 2975 20 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 7782 CLARK MANAGER 7839 09-JUN-81 2450 10 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 10 rows selected.
10 ,找到各部门大于本部门平均薪水的员工:
SQL> select d.deptno, d.avgsal,e.ename,e.sal from emp e, (select deptno,avg(sal) avgsal from emp group by deptno) d where e.deptno=d.deptno and sal>=avgsal; DEPTNO AVGSAL ENAME SAL ---------- ---------- ---------- ---------- 30 1566.66667 ALLEN 1600 30 1566.66667 BLAKE 2850 10 4187.5 KING 5000 10 4187.5 tom_abc 8000 20 3839.28571 aaa 8000 20 3839.28571 aaa 8000 6 rows selected.
创建索引:
SQL> desc studet; Name Null? Type ----------------- -------- -------- ------------ SID NOT NULL NUMBER(2) SNAME NOT NULL VARCHAR2(14) EMAIL VARCHAR2(20) SEX VARCHAR2(1) AGE NUMBER(2) SQL> create index student_index on studet (sname); SQL> desc studet; Name Null? Type ------------------------ -------- --------------------- SID NOT NULL NUMBER(2) SNAME NOT NULL VARCHAR2(14) EMAIL VARCHAR2(20) SEX VARCHAR2(1) AGE NUMBER(2)
Linux 环境 Oracle Pro*C Oracle 编程:
官方文档:Pro*C/C++ Programmer‘s Guide:
http://docs.oracle.com/cd/E11882_01/appdev.112/e10825/toc.htm
Linux 下Oracle数据库的安装,
可以参考我的笔记:http://990487026.blog.51cto.com/10133282/1843639
配置proc编译器:
[oracle@oracle11 proc]$ vim /opt/oracle/app/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg 在后面加:/usr/lib/gcc/x86_64-redhat-linux/4.4.4/include 变成这样的: [oracle@oracle11 ~]$ cat /opt/oracle/app/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg sys_include=($ORACLE_HOME/precomp/public,/usr/include,/usr/lib/gcc-lib/x86_64-redhat-linux/3.2.3/include,/usr/lib/gcc/x86_64-redhat-linux/4.1.1/include,/usr/lib64/gcc/x86_64-suse-linux/4.1.0/include,/usr/lib64/gcc/x86_64-suse-linux/4.3/include,/usr/lib/gcc/x86_64-redhat-linux/4.4.4/include) ltype=short define=__x86_64__ [oracle@oracle11 ~]$ 如果不配置: Proc 编译,出现错误PCC-S-02015, unable to open include file 加选项parse=no也可以解决
[配置]vim 为pc文件高亮
[oracle@oracle11 ~]$ cat /home/oracle/.vimrc autocmd BufEnter *.pc set filetype=esqlc
[Proc*C/C++编译配置]
proc的头文件在:/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ proc的动态库在:/opt/oracle/app/product/11.2.0/dbhome_1/lib/ 编译示例:$ proc hello.pc > /dev/null && gcc hello.c -I/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ -L/opt/oracle/app/product/11.2.0/dbhome_1/lib/ -lclntsh && ./a.out
Oracle数据类型
proc小试身手
[oracle@oracle11 proc]$ cat hello.pc #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { printf("Hello \n"); return 0; } [oracle@oracle11 proc]$ proc编译:[oracle@oracle11 proc]$ proc parse=no hello.pc gcc 编译:[oracle@oracle11 proc]$ gcc hello.c && ./a.out Hello 一键联编: [oracle@oracle11 proc]$ proc hello.pc > /dev/null && gcc hello.c && ./a.out Hello [oracle@oracle11 proc]$
C语言方式:SQL 内嵌语法:
[oracle@oracle11 proc]$ cat hello.pc #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlca.h" //定义宿主变量 EXEC SQL BEGIN DECLARE SECTION; char *serverid="scott/11@orcl"; EXEC SQL END DECLARE SECTION; int main() { int ret = 0; printf("Hello \n"); //嵌入式SQL语句必须以 EXEC SQL 开头 EXEC SQL connect:serverid;//妈蛋,这是谁龟腚的语法 if(sqlca.sqlcode != 0) { ret = sqlca.sqlcode; printf("EXEC SQL connect:serverid err \n"); exit(1); } printf("connect ok!\n"); return ret; } [oracle@oracle11 proc]$ proc hello.pc > /dev/null && gcc hello.c -I/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ -L/opt/oracle/app/product/11.2.0/dbhome_1/lib/ -lclntsh && ./a.out Hello connect ok! [oracle@oracle11 proc]$ 编译很烦:Makefile就好用了 [oracle@oracle11 proc]$ proc hello.pc > /dev/null [oracle@oracle11 proc]$ gcc hello.c -I/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ -L/opt/oracle/app/product/11.2.0/dbhome_1/lib/ -lclntsh [oracle@oracle11 proc]$ ./a.out
C++方式,SQL 内嵌语法:
[oracle@oracle11 proc]$ cat c++_hello.pc #include <iostream> #include <stdlib.h> #include <string.h> #include "sqlca.h" using namespace std; //定义宿主变量 EXEC SQL BEGIN DECLARE SECTION; char *serverid="scott/11@orcl"; EXEC SQL END DECLARE SECTION; int main() { int ret = 0; //printf("Hello \n"); cout << "hello c++ sql\n"; //嵌入式SQL语句必须以 EXEC SQL 开头 EXEC SQL connect:serverid;//妈蛋,这是谁龟腚的语法 if(sqlca.sqlcode != 0) { ret = sqlca.sqlcode; cout<<"EXEC SQL connect:serverid err \n"; exit(1); } cout<<"connect ok!\n"; return ret; } [oracle@oracle11 proc]$ proc iname=./c++_hello.pc oname=c++_hello.cpp PARSE=NONE CODE=cpp > /dev/null && g++ c++_hello.cpp -I/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ -L/opt/oracle/app/product/11.2.0/dbhome_1/lib/ -lclntsh && ./a.out c++_hello.cpp:153: warning: deprecated conversion from string constant to ‘char*’ hello c++ sql connect ok! [oracle@oracle11 proc]$ proc编译c++需要配置一下 [oracle@oracle11 proc] $ proc iname=./c++_hello.pc oname=c++_hello.cpp PARSE=NONE CODE=cpp > /dev/null && g++ c++_hello.cpp -I/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ -L/opt/oracle/app/product/11.2.0/dbhome_1/lib/ -lclntsh && ./a.out
Pro*C 编程:insert into 向数据库插入数据:
[oracle@oracle11 proc]$ cat db_op.pc #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlca.h" //定义宿主变量 EXEC SQL BEGIN DECLARE SECTION; char *serverid="scott/11@orcl"; int deptno = 0; char dname[20]; char loc[20]; EXEC SQL END DECLARE SECTION; int main() { int ret = 0; printf("Hello \n"); //嵌入式SQL语句必须以 EXEC SQL 开头 EXEC SQL connect:serverid; if(sqlca.sqlcode != 0) { ret = sqlca.sqlcode; printf("EXEC SQL connect:serverid err \n"); exit(1); } deptno =50; strcpy(dname,"oracle"); strcpy(loc,"China"); EXEC SQL insert into dept (deptno,dname,loc) values(:deptno,:dname,:loc); EXEC SQL commit; //EXEC SQL commit RELEASE;提交事务并断开连接 printf("connect ok!\n"); return ret; } [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc db_op.pc gcc db_op.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh ./a.out [oracle@oracle11 proc]$ bash comp Pro*C/C++: Release 11.2.0.1.0 - Production on Mon Aug 29 03:09:12 2016 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. System default option values taken from: /opt/oracle/app/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg Hello connect ok! 开一个窗口:验证 SQL> select * from dept; DEPTNO DNAME LOC ---------- -------------- ------------- 50 oracle China 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON
Pro*C 编程:update 向数据库更新数据:
[oracle@oracle11 proc]$ cat db_op.pc #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlca.h" //定义宿主变量 EXEC SQL BEGIN DECLARE SECTION; char *serverid="scott/11@orcl"; int deptno = 0; char dname[20]; char loc[20]; EXEC SQL END DECLARE SECTION; int main() { int ret = 0; printf("Hello \n"); //嵌入式SQL语句必须以 EXEC SQL 开头 EXEC SQL connect:serverid; if(sqlca.sqlcode != 0) { ret = sqlca.sqlcode; printf("EXEC SQL connect:serverid err \n"); exit(1); } deptno =50; strcpy(dname,"oracle"); strcpy(loc,"England"); EXEC SQL update dept set loc = :loc where deptno=:deptno; EXEC SQL commit; //EXEC SQL commit RELEASE;提交事务并断开连接 printf("connect ok!\n"); return ret; } [oracle@oracle11 proc]$ 编译小脚本: [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc db_op.pc gcc db_op.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh ./a.out 编译: [oracle@oracle11 proc]$ bash comp Pro*C/C++: Release 11.2.0.1.0 - Production on Mon Aug 29 03:14:01 2016 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. System default option values taken from: /opt/oracle/app/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg Hello connect ok! 验证: SQL> select * from dept; DEPTNO DNAME LOC ---------- -------------- ------------- 50 oracle England 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON SQL>
Pro*C 编程:select从数据库查数据:之char数据类型
[oracle@oracle11 proc]$ cat db_op.pc #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlca.h" EXEC SQL BEGIN DECLARE SECTION;//定义宿主变量 char *serverid="scott/11@orcl"; int deptno = 0; char dname[20]; char loc[20]; EXEC SQL END DECLARE SECTION; int main() { int ret = 0; printf("Hello \n"); EXEC SQL connect:serverid; //嵌入式SQL语句必须以 EXEC SQL 开头 if(sqlca.sqlcode != 0) { ret = sqlca.sqlcode; printf("EXEC SQL connect:serverid err \n"); exit(1); } printf("connect ok!\n"); strcpy(loc,"DALLAS"); EXEC SQL select deptno,dname,loc into:deptno,:dname,:loc from dept where loc=:loc; printf("deptno=%d,dname=%s,loc=%s\n",deptno,dname,loc); //EXEC SQL commit RELEASE;提交事务并断开连接 return ret; } [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc db_op.pc gcc db_op.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh ./a.out [oracle@oracle11 proc]$ bash comp Pro*C/C++: Release 11.2.0.1.0 - Production on Mon Aug 29 03:33:54 2016 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. System default option values taken from: /opt/oracle/app/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg Hello connect ok! deptno=20,dname=RESEARCH ,loc=DALLAS [oracle@oracle11 proc]$
Pro*C varchar 数据类型,自动去除占位的空格
[oracle@oracle11 proc]$ cat main.pc #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlca.h" EXEC SQL BEGIN DECLARE SECTION;//定义宿主变量,这可不是C风格的变量,虽然看起来像 char *serverid="scott/11@orcl"; int deptno = 0; char dname[20]; char loc[20]; int deptno2; varchar dname2[20]; varchar loc2[20]; EXEC SQL END DECLARE SECTION; int main() { int ret = 0; printf("正在连接ORACLE \n"); EXEC SQL connect:serverid; //嵌入式SQL语句必须以 EXEC SQL 开头 if(sqlca.sqlcode != 0) { ret = sqlca.sqlcode; printf("EXEC SQL connect:serverid err \n"); exit(1); } printf("连接成功!\n"); strcpy(loc,"DALLAS"); EXEC SQL select deptno,dname,loc into:deptno,:dname,:loc from dept where loc=:loc; printf("char SQL 风格: deptno=%d,dname=%s,loc=%s\n",deptno,dname,loc); EXEC SQL select deptno,dname,loc into:deptno2,:dname2,:loc2 from dept where deptno=20; //printf("varcher SQL风格:deptno=%d,dname=%s,loc=%s\n",deptno2,dname2,loc2); printf("varcher SQL风格:deptno=%d,dname=%s,loc=%s\n",deptno2,dname2.arr,loc2.arr); //EXEC SQL commit RELEASE;提交事务并断开连接 return ret; } [oracle@oracle11 proc]$ 编译小脚本: [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh ./a.out 开始编译运行: [oracle@oracle11 proc]$ bash comp Pro*C/C++: Release 11.2.0.1.0 - Production on Mon Aug 29 09:42:37 2016 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. System default option values taken from: /opt/oracle/app/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg 正在连接ORACLE 连接成功! char SQL 风格: deptno=20,dname=RESEARCH ,loc=DALLAS varcher SQL风格:deptno=40,dname=OPERATIONS,loc=BOSTON [oracle@oracle11 proc]$ bash comp Pro*C/C++: Release 11.2.0.1.0 - Production on Mon Aug 29 09:42:59 2016 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. System default option values taken from: /opt/oracle/app/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg 正在连接ORACLE 连接成功! char SQL 风格: deptno=20,dname=RESEARCH ,loc=DALLAS varcher SQL风格:deptno=20,dname=RESEARCH,loc=DALLAS [oracle@oracle11 proc]$
Pro*C string数据类型,自动去除占位的空格
[oracle@oracle11 proc]$ cat main.pc #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlca.h" typedef char dnameType[20]; typedef char locType[20]; EXEC SQL BEGIN DECLARE SECTION;//定义宿主变量,这可不是C风格的变量,虽然看起来像 char *serverid="scott/11@orcl"; int deptno_1; char dname_1[20]; char loc_1[20]; EXEC SQL TYPE dnameType is string(20); EXEC SQL TYPE locType is string(20); int deptno_2; dnameType dname_2; locType loc_2; EXEC SQL END DECLARE SECTION; int main() { int ret = 0; printf("正在连接ORACLE \n"); EXEC SQL connect:serverid; //嵌入式SQL语句必须以 EXEC SQL 开头 if(sqlca.sqlcode != 0) { ret = sqlca.sqlcode; printf("EXEC SQL connect:serverid err \n"); exit(1); } printf("连接成功!\n"); EXEC SQL select deptno,dname,loc into:deptno_1,:dname_1,:loc_1 from dept where deptno=20; printf("char SQL 风格:deptno=%d,dname=%s,loc=%s\n",deptno_1,dname_1,loc_1); EXEC SQL select deptno,dname,loc into:deptno_2,:dname_2,:loc_2 from dept where deptno=20; printf("string SQL 风格:deptno=%d,dname=%s,loc=%s\n",deptno_2,dname_2,loc_2); //EXEC SQL commit RELEASE;提交事务并断开连接 return ret; } 编译小脚本: [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh ./a.out 编译运行: [oracle@oracle11 proc]$ bash comp 正在连接ORACLE 连接成功! char SQL 风格:deptno=20,dname=RESEARCH ,loc=DALLAS string SQL 风格:deptno=20,dname=RESEARCH,loc=DALLAS [oracle@oracle11 proc]$
NULL问题,1,插入数据时,字段填NULL
[oracle@oracle11 proc]$ cat main.pc #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlca.h" typedef char dnameType[20]; typedef char locType[20]; EXEC SQL BEGIN DECLARE SECTION;//定义宿主变量,这可不是C风格的变量,虽然看起来像 char *serverid="scott/11@orcl"; int deptno; char dname[20]; short dname_ind; //指示器变量 char loc[20]; short loc_ind; //指示器变量 EXEC SQL TYPE dnameType is string(20); EXEC SQL TYPE locType is string(20); int deptno_2; dnameType dname_2; locType loc_2; EXEC SQL END DECLARE SECTION; int main() { int ret = 0; printf("正在连接ORACLE \n"); EXEC SQL connect:serverid; //嵌入式SQL语句必须以 EXEC SQL 开头 if(sqlca.sqlcode != 0) { ret = sqlca.sqlcode; printf("EXEC SQL connect:serverid err \n"); exit(1); } printf("连接成功!\n"); loc_ind = -1; deptno = 60; strcpy(dname,"oracle"); strcpy(loc,"China"); EXEC SQL insert into dept (deptno,dname,loc) values(:deptno,:dname,:loc:loc_ind); EXEC SQL commit RELEASE; //提交事务并断开连接 return ret; } 编译小脚本: [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh ./a.out [oracle@oracle11 proc]$ 编译运行: [oracle@oracle11 proc]$ bash comp Pro*C/C++: Release 11.2.0.1.0 - Production on Mon Aug 29 10:50:00 2016 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. System default option values taken from: /opt/oracle/app/product/11.2.0/dbhome_1//precomp/admin/pcscfg.cfg 正在连接ORACLE 连接成功! [oracle@oracle11 proc]$ 验证: SQL> select * from dept; DEPTNO DNAME LOC ---------- -------------- ------------- 60 oracle 50 oracle England 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON 6 rows selected.
NULL问题,2,获取数据时,判断是否为NULL
[oracle@oracle11 proc]$ cat main.pc #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlca.h" typedef char dnameType[20]; typedef char locType[20]; EXEC SQL BEGIN DECLARE SECTION;//定义宿主变量,这可不是C风格的变量,虽然看起来像 char *serverid="scott/11@orcl"; int deptno; char dname[20]; short dname_ind; //指示器变量 char loc[20]; short loc_ind; //指示器变量 EXEC SQL TYPE dnameType is string(20); EXEC SQL TYPE locType is string(20); int deptno_2; dnameType dname_2; locType loc_2; EXEC SQL END DECLARE SECTION; int main() { int ret = 0; printf("正在连接ORACLE \n"); EXEC SQL connect:serverid; //嵌入式SQL语句必须以 EXEC SQL 开头 if(sqlca.sqlcode != 0) { ret = sqlca.sqlcode; printf("EXEC SQL connect:serverid err \n"); exit(1); } printf("连接成功!\n"); loc_ind = -1; deptno = 60; EXEC SQL select deptno, dname, loc into :deptno, :dname, :loc:loc_ind from dept where deptno=:deptno; if(loc_ind == -1) { strcpy(loc,"NULL"); } printf("deptno=%d,dname=%s,loc=%s\n",deptno,dname,loc); loc_ind = -1; deptno = 30; EXEC SQL select deptno, dname, loc into :deptno, :dname, :loc:loc_ind from dept where deptno=:deptno; if(loc_ind == -1) { strcpy(loc,"NULL"); } printf("deptno=%d,dname=%s,loc=%s\n",deptno,dname,loc); EXEC SQL commit RELEASE; //提交事务并断开连接 return ret; } 编译小脚本: [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh ./a.out 编译运行: [oracle@oracle11 proc]$ bash comp Pro*C/C++: Release 11.2.0.1.0 - Production on Mon Aug 29 11:13:24 2016 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. System default option values taken from: /opt/oracle/app/product/11.2.0/dbhome_1//precomp/admin/pcscfg.cfg 正在连接ORACLE 连接成功! deptno=60,dname=oracle ,loc=NULL deptno=30,dname=SALES ,loc=CHICAGO [oracle@oracle11 proc]$ 验证: SQL> select * from dept; DEPTNO DNAME LOC ---------- -------------- ------------- 60 oracle 50 oracle England 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON 6 rows selected.
Pro*C/C++ 编程,向Oracle 插入中文:
先把Linux,Oracle,Sqlplus设置为UTF8:
http://990487026.blog.51cto.com/10133282/1843858
[oracle@oracle11 proc]$ cat main.pc #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlca.h" EXEC SQL BEGIN DECLARE SECTION;//定义宿主变量,这可不是C风格的变量,虽然看起来像 char *serverid="scott/11@orcl"; int deptno; char dname[20]; char loc[20]; EXEC SQL END DECLARE SECTION; int main() { int ret = 0; printf("正在连接ORACLE \n"); EXEC SQL connect:serverid; //嵌入式SQL语句必须以 EXEC SQL 开头 if(sqlca.sqlcode != 0) { ret = sqlca.sqlcode; printf("EXEC SQL connect:serverid err \n"); exit(1); } printf("连接成功!\n"); deptno = 52; strcpy(dname,"浙"); strcpy(loc,"江"); EXEC SQL insert into dept(deptno,dname,loc) values(:deptno,:dname,:loc); EXEC SQL commit RELEASE; //提交事务并断开连接 return ret; } [oracle@oracle11 proc]$ 编译小脚本: [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh ./a.out 编译运行: [oracle@oracle11 proc]$ bash comp Pro*C/C++: Release 11.2.0.1.0 - Production on Mon Aug 29 13:38:08 2016 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. System default option values taken from: /opt/oracle/app/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg 正在连接ORACLE 连接成功! [oracle@oracle11 proc]$ 验证: SQL> select * from dept; 52 浙 江 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON 6 rows selected.
Oracle 通讯区 和错误处理:
[oracle@oracle11 proc]$ find /opt/oracle/ -name sqlca.h
/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/sqlca.h
演示登陆密码错误:
[oracle@oracle11 proc]$ cat main.pc #include <stdio.h> #include <string.h> #include <stdlib.h> #include "sqlca.h" EXEC SQL BEGIN DECLARE SECTION ;//先定义宿主变量 (SQL变量) char * serverid = "scott/tiger22@orcl"; int deptid; char DNAME[32]; char LOC[32]; EXEC SQL END DECLARE SECTION ; void sqlerr02() //错误SQL语言给打印出来 { char stm[120]; size_t sqlfc, stmlen=120; unsigned int ret = 0; printf("func sqlerr02() begin\n"); EXEC SQL WHENEVER SQLERROR CONTINUE; //出错时,可以把错误SQL语言给打印出来 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); } //main===> serverid==>sqlerr()==>EXEC SQL ROLLBACK WORK RELEASE;/==>sqlerr() int main() { int ret = 0; printf("hello....\n"); printf("serverid:%s \n", serverid); deptid = 63; strcpy(DNAME, "50name"); strcpy(LOC, "50loc"); EXEC SQL WHENEVER SQLERROR DO sqlerr(); EXEC SQL connect :serverid; if (sqlca.sqlcode != 0) { ret = sqlca.sqlcode ; printf("connect err:%d \n", ret); return ret; } else { printf("connect ok\n"); } EXEC SQL insert into dept(DEPTNO, DNAME, LOC) values(:deptid, :DNAME, :LOC); EXEC SQL COMMIT; printf("anter key continue ...delete...\n"); getchar(); getchar(); //EXEC SQL delete from dept where deptno= :deptid; printf("anter key continue ...update...\n"); getchar(); getchar(); strcpy(LOC, "50loclolo"); strcpy(LOC, "中国"); EXEC SQL update dept set loc= :LOC where deptno= :deptid; EXEC SQL COMMIT RELEASE; //提交事务断开连接 return ret; } 编译小脚本 [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh ./a.out 编译运行 [oracle@oracle11 proc]$ bash comp hello.... serverid:scott/tiger22@orcl err reason:ORA-01017: invalid username/password; logon denied [oracle@oracle11 proc]$
oerr错误码查看
[oracle@oracle11 proc]$ oerr ora 1017 01017, 00000, "invalid username/password; logon denied" // *Cause: // *Action: [oracle@oracle11 proc]$
游标的官方文档:
Cursors:
http://docs.oracle.com/cd/E11882_01/appdev.112/e10825/pc_06sql.htm#i2206
游标与数组:查询多条记录,全部插入一张表中
1,先创建一个空表:
SQL> create table like_dept as select * from dept where 1=2; SQL> select * from like_dept; no rows selected
程序:
[oracle@oracle11 proc]$ cat main.pc #include <stdio.h> #include <string.h> #include <stdlib.h> #include "sqlca.h" EXEC SQL BEGIN DECLARE SECTION ; //先定义宿主变量 (SQL变量) char * serverid = "scott/11@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 ; //错误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); } int main() { int ret = 0; int i = 0; int count; printf("位于主函数\n"); EXEC SQL WHENEVER SQLERROR DO sqlerr(); printf("已执行 EXEC SQL WHENEVER SQLERROR DO sqlerr()\n"); EXEC SQL connect :serverid; //EXEC SQL WHENEVER NOT FOUND CONTINUE; printf("111111111111....\n"); EXEC SQL select deptno, dname, loc into :deptno2, :dname2, :loc2:loc_ind from dept ; printf("22222222....\n"); count= sqlca.sqlerrd[2]; printf("select 返回%d条记录 \n", count); for (i=0; i<count; i++) { printf("%d, %s, %s\n", deptno2[i], dname2[i].arr, loc2[i].arr); } printf("333333333....\n"); EXEC SQL FOR :count insert into like_dept(deptno, dname, loc) values(:deptno2, :dname2, :loc2); EXEC SQL COMMIT RELEASE; //提交事务断开连接 return ret; } [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh ./a.out [oracle@oracle11 proc]$ bash comp 位于主函数 已执行 EXEC SQL WHENEVER SQLERROR DO sqlerr() 111111111111.... 22222222.... select 返回4条记录 10, ACCOUNTING, NEW YORK 20, RESEARCH, DALLAS 30, SALES, CHICAGO 40, OPERATIONS, BOSTON 333333333.... [oracle@oracle11 proc]$ 验证: SQL> select * from like_dept; 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON SQL>
用普通游标提取数据,一行一行的获取数据,就像单向链表
1,打造环境,建表填中文数据:
SQL> create table student (sid number(2) primary key, sname varchar2(50) not null,ADDRESS varchar2(50), sex varchar2(1),age number(2)); SQL> insert into student values(10,‘宋江‘,‘梁山第一把交椅‘,‘M‘,40); SQL> insert into student values(20,‘林冲‘,‘豹子头‘,‘M‘,30); SQL> insert into student values(20,‘吴用‘,‘智多星‘,‘M‘,30); SQL> insert into student values(22,‘吴用‘,‘智多星‘,‘M‘,30); SQL> insert into student values(23,‘鲁智深‘,‘花和尚‘,‘M‘,30); SQL> insert into student values(21,‘燕青‘,‘李师师‘,‘M‘,23); SQL> insert into student values(11,‘李逵‘,‘黑旋风‘,‘M‘,23); SQL> insert into student values(12,‘王伦‘,‘火并王伦‘,‘M‘,33); SQL> insert into student values(13,‘扈三娘‘,‘王爱虎‘,‘M‘,33); SQL> insert into student values(14,‘高俅老二‘,‘高衙内‘,‘M‘,33); SQL> insert into student values(15,‘西门庆‘,‘潘金莲‘,‘M‘,33); SQL> insert into student values(16,‘镇关西‘,‘卖猪肉‘,‘M‘,33); SQL> select * from student; 10 宋江 梁山第一把交椅 M 40 20 林冲 豹子头 M 30 22 吴用 智多星 M 30 23 鲁智深 花和尚 M 30 21 燕青 李师师 M 23 11 李逵 黑旋风 M 23 12 王伦 火并王伦 M 33 13 扈三娘 王爱虎 M 33 14 高俅老二 高衙内 M 33 15 西门庆 潘金莲 M 33 16 镇关西 卖猪肉 M 33 SQL> commit; Commit complete.
主程序:
[oracle@oracle11 proc]$ cat main.pc #include <stdio.h> #include <string.h> #include <stdlib.h> #include "sqlca.h" typedef char dnameType[80]; typedef char locType[80]; //演示普通游标查询数据 //需要注意点:如果程序查不到数据,要break出来 否则程序死循环 //游标中使用宿主数组提取数据 ----oracle9i proc*C/C++编程指南 第九章练习题4 //用游标来更新或者删除数据 EXEC SQL BEGIN DECLARE SECTION; EXEC SQL TYPE dnameType is string(50); EXEC SQL TYPE locType is string(50); char *usrname = "scott"; char *passwd = "11"; char *serverid = "orcl"; int deptno; dnameType dname; //string 数据类型 short dname_ind; locType loc; short loc_ind; EXEC SQL END DECLARE SECTION; extern sqlgls(char * , size_t *, size_t * ); extern sqlglmt(void *,char *,size_t *,size_t *); 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"); } } 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 ; } } int main() { int ret = 0; int i = 0; EXEC SQL WHENEVER SQLERROR DO sqlerr02(); connet(); EXEC SQL DECLARE c CURSOR FOR select SID,SNAME,ADDRESS from student; //1。定义游标 //EXEC SQL DECLARE c CURSOR FOR select deptno,dname,loc from dept; //1。定义游标 EXEC SQL OPEN c ; //2. 打开游标 EXEC SQL WHENEVER NOT FOUND DO BREAK; //3. 提取数据 fetch into while (1) { //printf("haha\n"); EXEC SQL FETCH c INTO :deptno,:dname,:loc:loc_ind; if (loc_ind == -1) { strcpy(loc, "null"); } printf("条目数:%d\t", sqlca.sqlerrd[2]); printf("%d, %s, %s \n", deptno, dname, loc); } EXEC SQL CLOSE c; //4 关闭游标 EXEC SQL COMMIT WORK RELEASE; return ret ; } 编译运行: [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh [oracle@oracle11 proc]$ bash comp [oracle@oracle11 proc]$ ./a.out connect ok... 条目数:1 10, 宋江, 梁山第一把交椅 条目数:2 20, 林冲, 豹子头 条目数:3 22, 吴用, 智多星 条目数:4 23, 鲁智深, 花和尚 条目数:5 21, 燕青, 李师师 条目数:6 11, 李逵, 黑旋风 条目数:7 12, 王伦, 火并王伦 条目数:8 13, 扈三娘, 王爱虎 条目数:9 14, 高俅老二, 高衙内 条目数:10 15, 西门庆, 潘金莲 条目数:11 16, 镇关西, 卖猪肉 [oracle@oracle11 proc]$
用滚动游标提取数据,可查询指定任意行数据:指哪儿打哪儿
相当于双向链表:数据库和表就用上面的例子
[oracle@oracle11 proc]$ cat main.pc //演示滚动游标查询数据 #include <stdio.h> #include <string.h> #include <stdlib.h> #include "sqlca.h" typedef char dnameType[20]; typedef char locType[20]; extern sqlgls(char * , size_t *, size_t * ); extern sqlglmt(void *,char *,size_t *,size_t *); EXEC SQL BEGIN DECLARE SECTION; EXEC SQL TYPE dnameType is string(20); EXEC SQL TYPE locType is string(20); char *usrname = "scott"; char *passwd = "11"; char *serverid = "orcl"; int deptno; dnameType dname; //string 数据类型 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"); } } 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 ; } } 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 c SCROLL CURSOR FOR select sid, sname,ADDRESS from student; EXEC SQL OPEN c; //2 打开游标 open cursor //EXEC SQL WHENEVER NOT FOUND DO break; //3 获取数据 fetch data //查询最后一条数据 EXEC SQL FETCH LAST c 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 c 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 c 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 c 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 c 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 c 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 c; EXEC SQL COMMIT WORK RELEASE; printf("return ok...\n"); return ret ; } [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh [oracle@oracle11 proc]$ bash comp Pro*C/C++: Release 11.2.0.1.0 - Production on Mon Aug 29 16:43:31 2016 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. System default option values taken from: /opt/oracle/app/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg [oracle@oracle11 proc]$ ./a.out connect ok... 16 镇关西 卖猪肉 10 宋江 梁山第一把交 22 吴用 智多星 11 李逵 黑旋风 12 王伦 火并王伦 11 李逵 黑旋风 return ok... [oracle@oracle11 proc]$
[难点]动态SQL,1,只能使用非select语法
[oracle@oracle11 proc]$ cat main.pc //演示dynamic-sql四种方法 #include <stdio.h> #include <string.h> #include <stdlib.h> #include "sqlca.h" #include "oraca.h" extern sqlgls(char * , size_t *, size_t * ); extern sqlglmt(void *,char *,size_t *,size_t *); 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 = "11"; char *serverid = "orcl"; int deptno; dnameType dname; //string 数据类型 //varchar类型 和 char 类型的区别. 与编译选项有关系 short dname_ind; locType loc; short loc_ind; char mySql[1024]; char *pSql; 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"); } } 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 ; } } //非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(); //EXEC SQL WHENEVER NOT FOUND DO nodata(); pSql = mySql; //循环处理sql语言 while(1) { 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 ; } [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh 编译: [oracle@oracle11 proc]$ bash comp 运行: [oracle@oracle11 proc]$ ./a.out connect ok... please enter sql(not select ): insert into dept values(68, ‘中‘, ‘国‘) mysql:insert into dept values(68, ‘中‘, ‘国‘) 任意键继续.... 继续执行吗? n return ok... [oracle@oracle11 proc]$ 验证: SQL> select * from dept; 68 中 国 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON
[难点]动态SQL,2,非查询语言, 带固定数量的宿主变量
//非查询语言, 带固定数量的宿主变量 //使用内嵌PREPARE命令准备SQL语言 //动态sql2 有2步骤 //1 PREPARE语法 EXEC SQL PREPARE statement_name FROM {:host_string | string_literal}; PREPARE是一个预编译器标识符,而不是宿主变量 //2 USING子句 EXEC SQL EXECUTE statement_name [USING :host_variable1[:indicator1] [, :host_variable2[:indicator2] ... ] ; [oracle@oracle11 proc]$ cat main.pc #include <stdio.h> #include <string.h> #include <stdlib.h> #include "sqlca.h" #include "oraca.h" extern sqlgls(char * , size_t *, size_t * ); extern sqlglmt(void *,char *,size_t *,size_t *); 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 = "11"; char *serverid = "orcl"; int deptno; dnameType dname; //string 数据类型 //varchar类型 和 char 类型的区别. 与编译选项有关系 short dname_ind; locType loc; short loc_ind; char mySql[1024]; char *pSql; 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"); } } 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 ; } } 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(); pSql = mySql; //循环处理sql语言 for(;;) { printf("\n请输入要更新部门编号 "); scanf("%d", &deptno); printf("\n请输入要新loc值 "); scanf("%s", loc); //准备动态sql EXEC SQL PREPARE my_pre_sql FROM ‘update dept set loc = :a where deptno = :b‘; //执行动态sql EXEC 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 ; } [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh [oracle@oracle11 proc]$ 编译运行: [oracle@oracle11 proc]$ bash comp [oracle@oracle11 proc]$ ./a.out connect ok... 请输入要更新部门编号 68 请输入要新loc值 浙江 按任意键继续? 退出键入n, 其他继续? n return ok... [oracle@oracle11 proc]$ 验证: SQL> select * from dept; 68 中 国 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON SQL> select * from dept; 68 中 浙江 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON SQL>
[难点]动态SQL,3 处理选择列表项(select查询出来的结果列数固定)
查询部门号大于10的所有部门信息 动态sql3 处理选择列表项(select查询出来的结果列数固定) 和 输入宿主变量个数一定 本质: 输入宿主变量个数固定 查询条件固定 输出宿主变量个数固定 返回结果固定 可以结合游标一块使用 [oracle@oracle11 proc]$ cat main.pc #include <stdio.h> #include <string.h> #include <stdlib.h> #include "sqlca.h" #include "oraca.h" extern sqlgls(char * , size_t *, size_t * ); extern sqlglmt(void *,char *,size_t *,size_t *); 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 = "11"; char *serverid = "orcl"; int deptno; dnameType dname; //string 数据类型 //varchar类型 和 char 类型的区别. 与编译选项有关系 short dname_ind; locType loc; short loc_ind; char mySql[1024]; char *pSql; 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"); } } 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 ; } } 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语言 printf("程序会输出大于指定部门编号的所有信息\n"); while(1) { printf("请输入部门编号 "); scanf("%d", &deptno); EXEC SQL PREPARE my_pre_sql3 FROM ‘select deptno, dname, loc from dept where deptno > :a‘;//准备动态sql 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,%s,%s\n", deptno, dname, loc); } EXEC SQL CLOSE c1; EXEC SQL COMMIT; printf("\n键入 n 退出, 其他继续\n"); scanf("%c", &choosechar); fflush(stdin); if (choosechar==‘n‘ || choosechar==‘N‘) { break; } } EXEC SQL COMMIT WORK RELEASE; printf("return ok...\n"); return ret ; } [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh [oracle@oracle11 proc]$ bash comp Pro*C/C++: Release 11.2.0.1.0 - Production on Mon Aug 29 18:23:41 2016 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. System default option values taken from: /opt/oracle/app/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg [oracle@oracle11 proc]$ ./a.out connect ok... 程序会输出大于指定部门编号的所有信息 请输入部门编号 11 20,RESEARCH,DALLAS 30,SALES,CHICAGO 40,OPERATIONS,BOSTON 68,中,杭州 键入 n 退出, 其他继续 请输入部门编号 n 键入 n 退出, 其他继续 return ok... [oracle@oracle11 proc]$ 验证: SQL> select * from dept; 68 中 杭州 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON SQL>
[难点]动态SQL4,具备完整select 语法 ANSI方法
支持任意列宽的select proc编译选项: MODE=ANSI|ISO|ANSI14|ISO14|ANSI13|ISO13|ORACLE; 缺省值为ORACLE。指定程序遵循的标准。 [难,5年的员工看起来也吃力]Oracle开发就是这么难!!!! 主程序: [oracle@oracle11 proc]$ cat main.pc /* sqlcheck=full */ /* userid=scott/password@exam */ /* mode=ansi */ // proc /* 包含C头文件 */ #include <stdio.h> #include <string.h> /* 包含SQLCA头文件 */ #include <sqlca.h> /* 定义绑定变量值和 选择列表项值的最大长度 */ #define MAX_VAR_LEN 30 /* 定义选择列表项名的最大长度 */ #define MAX_NAME_LEN 31 /* 定义宿主变量 */ exec sql begin declare section; char *usrname = "scott"; char *passwd = "11"; char *serverid = "orcl"; char sql_stat[100]; char current_date[20]; exec sql end declare section; void sql_error(); void connet(); void process_input(); void process_output(); int main() { /* 安装错误处理句柄 */ exec sql whenever sqlerror do sql_error(); /* 连接到数据库 */ connet(); /* 分配输入描述区和输出描述区 */ exec sql allocate descriptor ‘input_descriptor‘; exec sql allocate descriptor ‘output_descriptor‘; for( ; ; ) { printf("\n请输入动态SQL语句(EXIT:退出):\n"); gets(sql_stat); /* EXIT(exit)->退出 */ if(0 == strncmp(sql_stat , "EXIT" , 4) || 0 == strncmp(sql_stat , "exit" , 4)) break; /* 准备动态SQL语句 */ exec sql prepare s from :sql_stat; /* 定义游标 */ exec sql declare c cursor for s; /* 处理绑定变量 */ process_input(); /* 打开游标 * select语句:处理查询结果 * 其他SQL语句:执行 */ exec sql open c using descriptor ‘input_descriptor‘; if(0 == strncmp(sql_stat , "SELECT" , 6) , 0 == strncmp(sql_stat , "select" , 6)) { process_output(); } /* 关闭游标 */ exec sql close c; } /* 释放输入描述区和输出描述区 */ exec sql deallocate descriptor ‘input_descriptor‘; exec sql deallocate descriptor ‘output_descriptor‘; /* 提交事务,断开连接 */ exec sql commit work release; puts("谢谢使用ANSI动态SQL!\n"); return 0; } void sql_error() { /* 显示SQL错误 */ printf("%.*s\n" , sqlca.sqlerrm.sqlerrml , sqlca.sqlerrm.sqlerrmc); exit(0); } void process_input() { int i; /* 定义宿主变量 */ exec sql begin declare section; int input_count; int input_type ; int input_len; char input_buffer[MAX_VAR_LEN]; char name[MAX_NAME_LEN]; int occurs; exec sql end declare section; /* 绑定变量->输入描述区 */ exec sql describe input s using descriptor ‘input_descriptor‘; /* 取得绑定变量个数 */ exec sql get descriptor ‘input_descriptor‘ :input_count = count; /* 循环处理绑定变量名 */ for(i = 0 ; i != input_count ; ++i) { occurs = i + 1; /* 取得绑定变量名 */ exec sql get descriptor ‘input_descriptor‘ value :occurs :name = name; printf("请输入%s的值:" , name); gets(input_buffer); /* 以NULL结尾 */ input_len = strlen(input_buffer); input_buffer[input_len] = ‘\0‘; /* 设置绑定变量类型、长度和值 */ input_type = 1; exec sql set descriptor ‘input_descriptor‘ value :occurs type = :input_type , length = :input_len , data = :input_buffer; } } void process_output() { int i; // 定义宿主变量 EXEC SQL BEGIN DECLARE SECTION ; int output_count; int output_type; int output_len; char output_buffer[MAX_VAR_LEN]; short output_indicator; char name[MAX_NAME_LEN]; int occurs; EXEC SQL END DECLARE SECTION ; // 选择列表项->输出描述区 exec sql describe output s using descriptor ‘output_descriptor‘; //取得选择列表项个数 exec sql get descriptor ‘output_descriptor‘ :output_count = count; //循环处理选择列表项 (显示表头;设置显示。数据按照字符串格式) output_type = 12; //note //设置类型为变长字符串 //output_type = 1; //note for(i = 0 ; i != output_count ; ++i) { occurs = i + 1; output_len = MAX_VAR_LEN; //printf("22222222222222:%d \n", i); // 设置选择列表项的类型和长度 exec sql set descriptor ‘output_descriptor‘ value :occurs type = :output_type , length = :output_len; //取得选择列表项的名称并输出 exec sql get descriptor ‘output_descriptor‘ value :occurs :name = name; //显示选择列表项名称 printf("\t%s" , name); } printf("\n"); // 提取数据完毕->退出循环 exec sql whenever not found do break; // 循环处理选择列表项数据 for( ; ; ) { // 行数据->输出描述区 exec sql fetch c into descriptor ‘output_descriptor‘; // 循环处理每列数据 for(i = 0 ; i < output_count ; ++i) { occurs = i +1; // 取得列数据和指示变量值 exec sql get descriptor ‘output_descriptor‘ VALUE :occurs :output_buffer = DATA , :output_indicator = INDICATOR; //输出列数据 if(-1 == output_indicator) printf("\t%s", " "); else printf("\t%s" , output_buffer); } printf("\n"); } } 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"); } } [oracle@oracle11 proc]$ 编译小脚本: [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc mode=ansi main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh [oracle@oracle11 proc]$ 编译运行: [oracle@oracle11 proc]$ bash comp Pro*C/C++: Release 11.2.0.1.0 - Production on Mon Aug 29 19:10:40 2016 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. System default option values taken from: /opt/oracle/app/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg main.c: In function ‘sql_error’: main.c:440: warning: incompatible implicit declaration of built-in function ‘exit’ /tmp/ccys6Bg9.o: In function `main‘: main.c:(.text+0x174): warning: the `gets‘ function is dangerous and should not be used. 运行: [oracle@oracle11 proc]$ ./a.out connect ok... 请输入动态SQL语句(EXIT:退出): select * from dept DEPTNO DNAME LOC 68 中 杭州 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON 请输入动态SQL语句(EXIT:退出): exit 谢谢使用ANSI动态SQL! [oracle@oracle11 proc]$ [oracle@oracle11 proc]$ ./a.out connect ok... 请输入动态SQL语句(EXIT:退出): select * from emp EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO 7369 SMITH CLERK 7902 17-DEC-80 800 20 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7566 JONES MANAGER 7839 02-APR-81 2975 20 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 7782 CLARK MANAGER 7839 09-JUN-81 2450 10 7788 SCOTT ANALYST 7566 19-APR-87 3000 20 7839 KING PRESIDENT 17-NOV-81 5000 10 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 7900 JAMES CLERK 7698 03-DEC-81 950 30 7902 FORD ANALYST 7566 03-DEC-81 3000 20 7934 MILLER CLERK 7782 23-JAN-82 1300 10 请输入动态SQL语句(EXIT:退出): exit 谢谢使用ANSI动态SQL! [oracle@oracle11 proc]$ 验证: SQL> select * from dept; 68 中 杭州 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON SQL> select * from emp; 7369 SMITH CLERK 7902 17-DEC-80 800 20 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7566 JONES MANAGER 7839 02-APR-81 2975 20 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 7782 CLARK MANAGER 7839 09-JUN-81 2450 10 7788 SCOTT ANALYST 7566 19-APR-87 3000 20 7839 KING PRESIDENT 17-NOV-81 5000 10 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 7900 JAMES CLERK 7698 03-DEC-81 950 30 7902 FORD ANALYST 7566 03-DEC-81 3000 20 7934 MILLER CLERK 7782 23-JAN-82 1300 10 14 rows selected. SQL>
[难点]动态SQL4,具备完整select 语法Oracle官方方法
方法4,Oracle官方方法,可做简历案例 难点1,内存分配 难点2,数据的展示 [oracle@oracle11 proc]$ cat main.pc /* 包含C头文件 */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <setjmp.h> #include <sqlcpr.h> /* 包含SQLDA和SQLCA结构 */ #include <sqlda.h> #include <sqlca.h> /* 定义绑定变量和选择列表项的最大个数 */ #define MAX_ITEMS 40 /* 定义绑定变量和选择列表项名称的最大长度 */ #define MAX_VNAME_LEN 30 /* 定义指示变量名称的最大长度 */ #define MAX_INAME_LEN 30 void connect(); void sql_error(); void alloc_descriptors(int , int , int); void dealloc_descriptors(); void set_bind_variables(); void process_select_list(); /* 定义绑定描述区和选择描述区 */ SQLDA* bind_dp; SQLDA* select_dp; /* 定义输入宿主变量:存放动态SQL语句 */ char sql_stat[100]; char current_date[20]; int main() { /* 安装错误处理句柄 */ exec sql whenever sqlerror do sql_error(); /* 连接到数据库 */ connect2(); /* 分配绑定描述区和选择描述区 */ alloc_descriptors(MAX_ITEMS , MAX_VNAME_LEN , MAX_INAME_LEN); for( ; ; ) { printf("请输入动态SQL语句(exit:退出):"); gets(sql_stat); /* EXIT(exit):退出 */ if(0 == strncmp(sql_stat , "exit" , 4) || 0 == strncmp(sql_stat , "EXIT" , 4)) break; /* 准备动态SQL语句 */ exec sql prepare s from :sql_stat; /* 定义游标 */ exec sql declare c cursor for s; /* 出错,继续下一循环 */ if(0 != sqlca.sqlcode) continue; /* 设置绑定变量 */ set_bind_variables(); /* * 打开游标 * select语句:生成结果集 * 其他SQL语句:执行语句 */ exec sql open c using descriptor bind_dp; /* * select语句 */ if(0 == strncmp(sql_stat , "select" , 6) || 0 == strncmp(sql_stat , "SELECT" , 6)) { process_select_list(); } /* 关闭游标 */ exec sql close c; } /* 释放选择描述区和选择描述区 */ dealloc_descriptors(); /* 提交事务,断开连接 */ exec sql commit work release; puts("谢谢使用Oracle动态SQL方法四!\n"); return 0; } void connect2() { /* 定义宿主变量 */ char username[20] , password[20] , server[20]; /* 输入用户名、口令和网络服务名 */ printf("username:"); gets(username); printf("password: "); gets(password); printf("server:"); gets(server); /* 连接到数据库 */ EXEC SQL CONNECT :username identified by :password using :server; } //struct SQLDA { /* ub4 */ int N; /* Descriptor size in number of entries */ /* text** */ char **V; /* Ptr to Arr of addresses of main variables */ /* ub4* */ int *L; /* Ptr to Arr of lengths of buffers */ /* sb2* */ short *T; /* Ptr to Arr of types of buffers */ /* sb2** */ short **I; /* Ptr to Arr of addresses of indicator vars */ /* sb4 */ int F; /* Number of variables found by DESCRIBE */ /* text** */ char **S; /* Ptr to Arr of variable name pointers */ /* ub2* */ short *M; /* Ptr to Arr of max lengths of var. names */ /* ub2* */ short *C; /* Ptr to Arr of current lengths of var. names */ /* text** */ char **X; /* Ptr to Arr of ind. var. name pointers */ /* ub2* */ short *Y; /* Ptr to Arr of max lengths of ind. var. names*/ /* ub2* */ short *Z; /* Ptr to Arr of cur lengths of ind. var. names*/ // }; /* char ** getMeme(int size) { int i; char **tmp = (char **)malloc(sizeof(char *) *size); for (i=0; i<size; i++) { tmp[i] = (char *)malloc(40); } return tmp; } void SQLSQLDAAlloc(0 , size , MAX_VNAME_LEN , MAX_INAME_LEN) { struct SQLDA *sqlda = (struct SQLDA *)malloc(sizeof(struct SQLDA )); sqlda->v = (char **)malloc(sizeof(char *) * size); sqlda->I = (char **)malloc(sizeof(char *) * size); sqlda->S = (char **)malloc(sizeof(char *) * size); sqlda->X = (char **)malloc(sizeof(char *) * size); sqlda->L = (int *)malloc(size*sizeof(int)); sqlda->T = (short *)malloc(size*sizeof(short)); //.. //.... return sqlda; } */ void sql_error() { /* 显示SQL错误信息 */ printf("%.*s\n" , sqlca.sqlerrm.sqlerrml , sqlca.sqlerrm.sqlerrmc); } void alloc_descriptors(int size , int max_vname_len , int max_iname_len) { int i; /* 分配绑定描述区和选择描述区 */ bind_dp = SQLSQLDAAlloc(0 , size , MAX_VNAME_LEN , MAX_INAME_LEN); select_dp = SQLSQLDAAlloc(0 , size , MAX_VNAME_LEN , MAX_INAME_LEN); /* 为指示变量、绑定变量和选择列表项分配内存 */ for(i = 0 ; i != MAX_ITEMS ; ++i) { bind_dp->I[i] = (short*)malloc(sizeof(short)); select_dp->I[i] = (short*)malloc(sizeof(short)); bind_dp->V[i] = (char*)malloc(1); select_dp->V[i] = (char*)malloc(1); } } void dealloc_descriptors() { int i; /* 释放指示变量、绑定变量和选择列表项占用的内存 */ for(i = 0 ; i != MAX_ITEMS ; ++i) { if(bind_dp->V[i] != (char*)0) free(bind_dp->V[i]); free(bind_dp->I[i]); if(select_dp->V[i] != (char*)0) free(select_dp->V[i]); free(select_dp->I[i]); } /* 释放绑定描述区和选择描述区 */ SQLSQLDAFree(0 , bind_dp); SQLSQLDAFree(0 , select_dp); } void set_bind_variables() { int i; char bind_var[64]; /* 设置绑定变量最大个数 */ bind_dp->N = MAX_ITEMS; /* 绑定变量名称: 绑定描述区 */ exec sql describe bind variables for s into bind_dp; /* 设置绑定变量实际个数 */ bind_dp->N = bind_dp->F; /* 循环处理绑定变量 */ for(i = 0 ; i != bind_dp->F ; ++i) { /* 显示绑定变量名 */ printf("请输入绑定变量%.*s的值:" , (int)bind_dp->C[i] , bind_dp->S[i]); /* 输入绑定变量的值 */ gets(bind_var); /* 设置绑定变量的长度成员 */ bind_dp->L[i] = strlen(bind_var); /* 为绑定变量数据缓冲区重新分配内存(多一位,留给‘\0‘) */ bind_dp->V[i] = (char*)realloc(bind_dp->V[i] , bind_dp->L[i] + 1); /* 绑定变量数据: 数据缓冲区 */ strcpy(bind_dp->V[i] , bind_var); /* 设置指示变量,处理NULL */ if(0 == strncmp(bind_var , "NULL" , 4) || 0 == strncmp(bind_var , "null" , 4)) *bind_dp->I[i] = -1; else *bind_dp->I[i] = 0; /* 设置数据缓冲区数据类型代码->char */ bind_dp->T[i] = 1; } } void process_select_list() { int i , null_ok , precision , scale; char title[MAX_VNAME_LEN]; /* 设置选择列表项的最大个数 */ select_dp->N = MAX_ITEMS; /* 选择列表项: 选择描述区 */ exec sql describe select list for s into select_dp; /* 设置选择列表项的实际个数 */ select_dp->N = select_dp->F; /* 循环处理选择列表项 */ for(i = 0 ; i != select_dp->F ; ++i) { /* 清除select_dp->T[i]的高位->null */ SQLColumnNullCheck(0 , (unsigned short*)&select_dp->T[i] , (unsigned short*)&select_dp->T[i] , &null_ok); /* 根据内部数据类型确定外部类型数据长度(显示长度) */ switch(select_dp->T[i]) { case 2: /* number类型,取得精度与标度 */ //SQLNumberPrecV6(0 , (unsigned short*)&select_dp->T[i] , &precision , &scale); SQLNumberPrecV6(0 , (unsigned long *)&select_dp->L[i] , &precision , &scale); //wangbaoming modify 201409 if(scale > 0) /* 实数: 显示长度:float */ select_dp->L[i] = sizeof(float); else /* 整数: 显示长度 int */ select_dp->L[i] = sizeof(int); break; case 12: /* DATA数据类型(DD-MON-YY) */ select_dp->L[i] = 9; break; } /* 根据变量长度,重新为选择列表项数据缓冲区分配内存 */ if(2 != select_dp->T[i]) /* 其他类型 */ select_dp->V[i] = (char*)realloc(select_dp->V[i] , select_dp->L[i] + 1); else /* number类型 */ select_dp->V[i] = (char*)realloc(select_dp->V[i] , select_dp->L[i]); /* 初始化title */ memset(title , ‘ ‘ , MAX_VNAME_LEN); /* 选择列表项名称: title */ strncpy(title , select_dp->S[i] , select_dp->C[i]); /* 显示列名 */ if(2 == select_dp->T[i]) if(scale > 0) printf("\t%.*s" , select_dp->L[i] + 3, title); else printf("\t%.*s" , select_dp->L[i] , title); else printf("\t%-.*s" , select_dp->L[i] , title); /* 根据Oracle内部类型确定外部数据类型(显示类型) */ if( 2 == select_dp->T[i]) { /* number 类型*/ if(scale > 0) /* float */ select_dp->T[i] = 4; else /* int */ select_dp->T[i] = 3; } else /* char */ select_dp->T[i] = 1; } printf("\n"); /* 提取数据完毕->结束循环 */ exec sql whenever not found do break; /* 循环处理选择列表数据 */ for( ; ; ) { /* 数据->选择描述区 */ exec sql fetch c using descriptor select_dp; /* 显示数据 */ for( i = 0 ; i != select_dp->F ; ++i) { if(*select_dp->I[i] < 0){ /* 处理NULL */ printf("\tNULL"); }else{ if(3 == select_dp->T[i]) { /* int */ printf("\t%d" , *(int*)select_dp->V[i]); }else if(4 == select_dp->T[i]){ /* float */ printf("\t%8.2f" , *(float*)select_dp->V[i]); }else{ /* char */ printf("\t%.*s" , select_dp->L[i] , select_dp->V[i]); } } } printf("\n"); } } [oracle@oracle11 proc]$ 编译脚本 [oracle@oracle11 proc]$ cat comp INCLUDE_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/ LD_PATH=/opt/oracle/app/product/11.2.0/dbhome_1/lib/ proc mode=oracle sqlcheck=full main.pc gcc main.c -I$INCLUDE_PATH -L$LD_PATH -lclntsh 开始编译: [oracle@oracle11 proc]$ bash comp Pro*C/C++: Release 11.2.0.1.0 - Production on Mon Aug 29 19:49:55 2016 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. System default option values taken from: /opt/oracle/app/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg main.c:357: warning: conflicting types for ‘connect2’ main.c:190: note: previous implicit declaration of ‘connect2’ was here main.c: In function ‘process_select_list’: main.c:667: warning: passing argument 2 of ‘sqlprct’ from incompatible pointer type /opt/oracle/app/product/11.2.0/dbhome_1/precomp/public/sqlcpr.h:88: note: expected ‘unsigned int *’ but argument is of type ‘long unsigned int *’ /tmp/cc7GfpD0.o: In function `main‘: main.c:(.text+0x44): warning: the `gets‘ function is dangerous and should not be used. [oracle@oracle11 proc]$ 运行: [oracle@oracle11 proc]$ ./a.out username:scott password: 11 server:orcl 请输入动态SQL语句(exit:退出):select * from emp EMPN ENAME JOB MGR HIREDATE SAL COMM DEPT 7369 SMITH CLERK 7902 17-DEC-80 800.00 NULL 20 7499 ALLEN SALESMAN 7698 20-FEB-81 1600.00 300.00 30 7521 WARD SALESMAN 7698 22-FEB-81 1250.00 500.00 30 7566 JONES MANAGER 7839 02-APR-81 2975.00 NULL 20 7654 MARTIN SALESMAN 7698 28-SEP-81 1250.00 1400.00 30 7698 BLAKE MANAGER 7839 01-MAY-81 2850.00 NULL 30 7782 CLARK MANAGER 7839 09-JUN-81 2450.00 NULL 10 7788 SCOTT ANALYST 7566 19-APR-87 3000.00 NULL 20 7839 KING PRESIDENT NULL 17-NOV-81 5000.00 NULL 10 7844 TURNER SALESMAN 7698 08-SEP-81 1500.00 0.00 30 7876 ADAMS CLERK 7788 23-MAY-87 1100.00 NULL 20 7900 JAMES CLERK 7698 03-DEC-81 950.00 NULL 30 7902 FORD ANALYST 7566 03-DEC-81 3000.00 NULL 20 7934 MILLER CLERK 7782 23-JAN-82 1300.00 NULL 10 请输入动态SQL语句(exit:退出):select * from student SID SNAME ADDRESS S AGE 10 宋江 梁山第一把交椅 M 40 20 林冲 豹子头 M 30 22 吴用 智多星 M 30 23 鲁智深 花和尚 M 30 21 燕青 李师师 M 23 11 李逵 黑旋风 M 23 12 王伦 火并王伦 M 33 13 扈三娘 王爱虎 M 33 14 高俅老二 高衙内 M 33 15 西门庆 潘金莲 M 33 16 镇关西 卖猪肉 M 33 请输入动态SQL语句(exit:退出):exit 谢谢使用Oracle动态SQL方法四! [oracle@oracle11 proc]$
本文出自 “魂斗罗” 博客,谢绝转载!
数据库编程4 Oracle Pro*C/C++开发