Proc、宿主变量、指示变量、数组变量、通信区sqlca,oraca ---(day07)
PROC
主要内容:
1) proc简介
2) proc程序的开发过程
3) 宿主变量和指示变量
4) 嵌入sql语句
5) 连接数据库
6) 错误处理
7) 数据的存取更新操作
8) 动态sql
-----------------------------
1.什么是pro程序?
1.1 概念
在过程化的编程语言中嵌入sql语句而开发出的应用程序,叫pro程序。
在通用的编程语言中嵌入的sql语句称为嵌入式sql
被嵌入了sql语句的编程语言称为宿主语言 1.2 proc/c++
在c/c++语言中嵌入sql语句而开发出的应用程序,称为proc/c++程序
目的:是C/C++这种高效的语言成为访问oracle数据库的工具 2. proc中嵌入的sql语句
#include .....
...
/* 包含一个名为sqlca的结构 */
exec sql include sqlca;
变量的声明
函数的声明 int main(void)
{
/* 连接数据库 */
exec sql connect:用户名/密码; /* 操作数据库:比如查询 */
exec sql select 字段列表 into 变量列表 from 表名
where 条件; /* 关闭并释放连接资源 */
exec sql commit work release;
exec sql rollbakc work release;
} 3.C程序的开发步骤
1) 编写源程序
vi xxx.c
2) 编译、链接
gcc xxx.c -lxxxxx
3) 运行
./a.out
4.proc程序的开发步骤
1) 编写源程序
vi xxxx.pc
2) 预编译 proc xxx.pc -----> xxx.c
3) 编译、链接
gcc xxx.c -lclntsh -- linux
gcc xxx.c -lorasql10(11) -- windows
4) 运行
./a.out 案例:first.pc
vi first.pc
proc first.pc
gcc first.c -lclntsh
./a.out 5. 宿主变量
5.1 概念
proc中C语言称为宿主语言
在宿主语言中定义,即可以在宿主语言中使用,也可以在sql语句中使用的变量,称为宿主变量。
5.2 宿主变量的数据类型
char 字符型
char var[n] 定长字符串
short
int 整型
long
float
double 浮点型
varchar var[n] 变长字符串 5.3 定长字符串和变长字符串
5.3.1 定长字符串
字符串的长度不足时用空格补齐 案例:charn.pc 5.3.2 变长字符串
案例:varcharn.pc char name[] ----> varchar name[25]
预编译时,varchar类型的数组被翻译成了同名的结构:
struct{
unsigned short len;
unsigned char arr[];
} name; varchar类型的数组在sql语句中使用时,和char型数组一样
在宿主语言中使用时,按照结构的用法:
提取字符串的值:name.arr
获取字符串的长度:name.len 使用varchar类型的数组时,可以会产生垃圾数据,解决方式:
1) 字符串进行初始化,把数组的所有元素初始化为'\0'
varchar name[] = {0};
2) 手动为字符串添加结束标志
name.arr[name.len] = '\0'; 5.3.3 使用预编译选项解决变长字符串的问题
oname 相当于 gcc 的 -o char_map = charz: 处理成定长,空格补齐,'\0'结尾
= varchar2|charf: 处理成定长,空格补齐,不以'\0'结尾
= string: 处理成变长,以'\0'结尾 proc charn.pc char_map=string
gcc charn.c -lclntsh
./a.out 5.4 宿主变量使用时的注意事项
1) 在sql语句中使用宿主变量时,最好在变量名前加:
...
int id=2;
...
exec sql select first_name into name from s_emp
where id=id;
...
2) DDL语句中不允许使用宿主变量
案例:droptable.pc
.....
char tablename[]="testdsql_zsm_00";
.....
/* 删除名为 tablename 的表 */
exec sql drop table tablename;
/* 预编译错误:宿主变量不能在ddl语句中使用 */
exec sql drop table :tablename;
3) 宿主变量可以使用指针,但是不推荐
4) 宿主变量的定义,强烈建议放入声明区
(C++语言、windows平台要求宿主变量的声明必须在声明区)
exec sql begin declare section;
/* 声明区 */
exec sql end declare section; 练习:定义合适的变量,接收s_dept中id=43的部门的信息,并输出。 案例:searchdeptbyid.pc
#include <stdio.h>
exec sql include sqlca;
int main(void)
{
exec sql begin declare section;
char userpasswd[]="openlab/open123";
int id=43;
char name[];
int rid;
exec sql end declare section;
exec sql connect :userpasswd;
exec sql select id,name,region_id
into :id,:name,:rid from s_dept
where id=:id;
exec sql commit work release;
printf("%d %s %d\n",id,name,rid);
return 0;
}
6.指示变量
6.1 指示变量的作用
当数据库中的字段的值,赋值给宿主变量时,赋值的状态了一通过指示变量获取。
指示变量的值:
0 代表正常赋值
-1 代表数据库中对应字段的值为null
>0 代表截断赋值 尽量避免(编译没问题,执行时在赋值阶段不会出现错误,引起的后续的问题 时机不确定) 6.2 语法
指示变量的数据类型必须是short
short indid;
short indname; exec sql select id,first_name into :id,:name
from s_emp where id=1; exec sq l select 字段1,字段2 into
:宿主变量1 [indicator] :指示变量 , 宿主变量2
from 表名 where 条件; exec sql select id,first_name into :id:indid,:name:indname
from s_emp where id=1; 6.3 案例:把s_emp表中id=1的员工的id,first_name,manager_id查询出来,保存到相应的宿主变量,同时使用指示变量指示赋值状态。 案例: indvar.pc 7.数组变量
7.1 数组变量使用的注意事项
1) 除了字符型外,其他类型的数组只能使用一维的
int ids[];
char name[][];
2) 不支持数组指针
3) 最大元素个数 32767
4) 在select语句中使用数组变量时,只能给出数组的名字,不能使用下标
5) 如果要指示多个变量的赋值状态,可以使用指示变量数组 7.2 把s_emp表中的所有员工的id,first_name和manager_id查询出来,使用合适的数组接收查询结果,并使用指示变量数组指示manager_id的赋值状态 案例:arr_var.pc
#include <stdio.h>
exec sql include sqlca;
int main(void)
{
exec sql begin declare section;
char userpasswd[]="openlab/open123";
int ids[]={0};
char names[][]={0};
int mids[]={0};
short indmids[]={-2};
exec sql end declare section;
exec sql connect:userpasswd;
exec sql select id,first_name,manager_id into
:ids,:names,:mids:indmids from s_emp;
exec sql commit work release;
int i=0;
for(;i<50;i++)
{
printf("%d %s %d %hd\n",ids[i],names[i],
mids[i],indmids[i]);
}
return 0;
}
8.sqlca通信区
8.1 通信区的概念
通信区:为了取得每个sql语句执行后的相关状态说明,以便进行错误的后续操作或跟踪
oracle中提供了两个通信区:
SQL通信区:sqlca
Oracle通信区:oraca 8.2 sqlca通信区
执行proc程序时,oracle把每一条sql中状态信息存入sqlca中,包括错误代码、警告标志设置、诊断文本和处理行数等。
本质上,sqlca是一个结构体
proc每执行一条sql语句,都会把相关信息写入到sqlca,覆盖上一条sql语句的执行的结果信息,所以需要获取执行结果信息的话,要执行完马上获取。 sqlca.sqlerrd[]: sql语句执行后影响的行数
sqlca.sqlcode: sql执行的状态
0: 执行正常
>0: 执行出错(出现异常)
<0 : 数据库系统错误 或者网络错误
sqlca.sqlerrm.sqlerrmc: 错误信息 案例:sqlca.pc
#include <stdio.h>
exec sql include sqlca;
int main(void)
{
exec sql begin declare section;
char userpasswd[]="openlab/open123";
int ids[]={0};
char names[][]={0};
int mids[]={0};
short indmids[]={-2};
exec sql end declare section;
exec sql connect:userpasswd;
if(sqlca.sqlcode){
printf("%s\n",sqlca.sqlerrm.sqlerrmc);
}
exec sql select id,first_name,manager_id into
:ids,:names,:mids:indmids from s_emp;
if(sqlca.sqlcode){
printf("%s\n",sqlca.sqlerrm.sqlerrmc);
}
exec sql commit work release;
int i=0;
for(;i<sqlca.sqlerrd[];i++)
{
printf("%d %s %d %hd\n",ids[i],names[i],
mids[i],indmids[i]);
}
return 0;
}
9. oraca通信区
一个类似于sqlca的结构,可以作为sqlca通信区的补充。当需要获取更为详细的状态信息,可以使用oraca.
oraca通信区对sqlca的补充
可以使用oraca获取执行的sql语句的文本 oraca的使用步骤:
1) 包含oraca
exec sql include oraca;
2) 打开oraca option
exec oracle option(oraca=yes);
3) 设置sql文本的保存标志
oraca.orastxtf
0: 默认值 不保存
1: sql语句出错时保存
2: sql语句出现错误或警告时保存
3: 都保存
4) 获取sql文本
oraca.orastxt.orastxtc 案例:oraca.pc
#include <stdio.h>
exec sql include sqlca;
exec sql include oraca;
exec oracle option(oraca=yes);
int main(void)
{
exec sql begin declare section;
char userpasswd[]="openlab/open123";
char name[];
int id=1;
exec sql end declare section;
exec sql connect:userpasswd;
oraca.orastxtf = 1;
exec sql select first_name into :name from s_emp
where id=:id;
exec sql commit work release;
printf("%s\n",name);
printf("%s\n",oraca.orastxt.orastxtc);
return 0;
}
10. proc中如何使用sql语句
1) select语句
在语句前加exec sql,配合into使用
exec sql select 字段列表 into 宿主变量列表 from 表名
where 条件;
2) dml语句(inert delete update)
ddl语句(create drop alter)
tcl语句(commit rollback savepoint)
直接在语句前加exec sql
注意:ddl语句中不能使用宿主变量 综合案例:sql.pc
#include <stdio.h>
#include <stdlib.h>
exec sql include sqlca;
int connect();
void createtable();
void insert();
void search();
void update();
void delete();
int main(void)
{
if(connect())
{
printf("连接错误\n");
return -1;
}
int option;
printf("欢迎使用学生管理系统\n");
while(1)
{
printf("1.创建学生表\n");
printf("2.注册\n");
printf("3.查看\n");
printf("4.修改\n");
printf("5.删除\n");
printf("0.退出\n");
printf("请选择:");
scanf("%d",&option);
switch(option)
{
case 1:
printf("学生管理系统---- 创建表\n\n");
createtable();
break;
case 2:
printf("学生管理系统---- 注册\n");
insert();
break;
case 3:
printf("学生管理系统---- 查看\n");
break;
case 4:
printf("学生管理系统---- 修改\n");
break;
case 5:
printf("学生管理系统---- 删除\n");
break;
case 0:
printf("谢谢使用!\n");
exit(0);
default:
printf("没有此功能!\n");
break;
}
}
return 0;
}
int connect()
{
exec sql begin declare section;
char username[];
char passwd[];
exec sql end declare section;
printf("请输入用户名:");
scanf("%s",username);
printf("请输入密码:");
scanf("%s",passwd);
exec sql connect:username identified by :passwd;
return sqlca.sqlcode;
}
void createtable()
{
exec sql create table student_zsm_00(
stuno number(7),
stuname varchar2(20),
birth date);
}
void insert()
{
exec sql begin declare section;
int stuno;
char name[];
char birth[];
exec sql end declare section;
printf("请输入学号:");
scanf("%d",&stuno);
printf("请输入姓名:");
scanf("%s",name);
printf("请输入出生日期:(yyyy-mm-dd)");
scanf("%s",birth);
exec sql insert into student_zsm_00 values(
:stuno,:name,to_date(:birth,'yyyy-mm-dd'));
exec sql commit;
}
开发一个超小型的学生管理系统,完成以下功能:
创建学生信息表
添加学生信息
显示学生信息列表
根据学号更改信息
根据学号删除信息 循环菜单:
学生管理系统,请选择:
1.创建表
2.学生注册
3.查看
4.修改信息
5.删除信息
0.退出 练习:
Proc、宿主变量、指示变量、数组变量、通信区sqlca,oraca ---(day07)的更多相关文章
- php 将几个变量合为数组,变量名和值对应
<?php $firstname = "Bill"; $lastname = "Gates"; $age = "60"; $resul ...
- 多动手试试,其实List类型的变量在页面上取到的值可以直接赋值给一个js的Array数组变量
多动手试试,其实List类型的变量在页面上取到的值可以直接赋值给一个js的Array数组变量,并且数组变量可以直接取到每一个元素var array1 = '<%=yearList =>'; ...
- perl5 第四章 列表和数组变量
第四章 列表和数组变量 by flamephoenix 一.列表二.数组--列表的存贮 1.数组的存取 2.字符串中的方括号和变量替换 3.列表范围 4.数组的输出 5.列表/数组的长度 ...
- 声明数组变量/// 计算所有元素的总和/打印所有元素总和/输出/foreach循环/数组作为函数的参数/调用printArray方法打印
实例 下面是这两种语法的代码示例: double[] myList; // 首选的方法 或 double myList[]; // 效果相同,但不是首选方法 创建数组 Java语言使用new操作符来创 ...
- block中无法使用C数组变量
在Objective-C的block中无法使用C数组,即使我们不对C数组做任何改变,编译的时候也会报错: #include <stdio.h> int main() { const cha ...
- java 数组变量与数组对象
数组是否必须初始化 对于这个问题,关键在于要弄清楚数组变量和数组对象的差别.数组变量是存放在栈内存中的,数组对象是存放在堆内存中的.数组变量只是一个引用变量,他能够指向实际的数组对象. 所谓的数组初始 ...
- 从一个微型例子看“C/C++的内存分配机制”和“数组变量名与指针变量名”(转)
C++的内存有五大分区:堆区.栈区.自由存储区.全局/静态存储区.常量存储区. 五个数据段:数据段.代码段.BSS段.堆.栈 内存分配方式有三种: 从静态存储区域分配.内存在程序编译的时候就已经分配好 ...
- shell变量定义与数组-1
1.查看系统所有shell和默认shell 查看系统所有的shell: cat /etc/shells 查看系统默认shell: echo $SHELL 2.第一个shell脚本,打印字符串Hello ...
- C语言中数组变量和指针变量
指针变量为什么需要类型? 数组变量和指针变量在使用sizeof时不同,sizeof(数组变量)是数组长度,sizeof(指针变量)是存储int的字节长度4或者8(64bit). 数组变量在参数传递中, ...
随机推荐
- Android学习笔记之:android更新ui的几种经常用法
Android主线程不能运行耗时操作.我们通常是在子线程中运行耗时操作, 我们在运行完耗时操作后,我们一般能够通过下面几种方式来实现ui界面的更新. 首先是布局文件: <LinearLayout ...
- poj和hdu部分基础算法分类及难度排序
最近想从头开始刷点基础些的题,正好有个网站有关于各大oj的题目分类(http://www.pythontip.com/acm/problemCategory),所以写了点脚本把hdu和poj的一些题目 ...
- javascript 数组,数组中加入新元素 push() ,unshift() 相当于Add()
<1> var a = []; //建立数组 push 方法 将新元素加入到一个数组中,并返回数组的新长度值.
- @PropertySource&@ImportResource&@Bean
@**PropertySource**:加载指定的配置文件: ```java /** * 将配置文件中配置的每一个属性的值,映射到这个组件中 * @ConfigurationProperties:告诉 ...
- java 将byte[]转为各种进制的字符串
public void test() { byte[] bytes = new byte[10000000]; for (int i = 0; i < 10000000; i++) { if ( ...
- 96.extjs 页面
1.登录js /** * @author sux * @desc 登录 */ Ext.onReady(function(){ Ext.QuickTips.init(); //错误信息显示必须 var ...
- 第2章 安装Nodejs 2-4 Linux下安装Nodejs
linux下编译安装Nodejs GCC和G++分别是GNU的C和C++编译器.它们在执行编译工作的时候把源代码通过预处理转化成汇编语言生成.i后缀的文件,再由汇编变成目标机器代码,最后连接目标代码 ...
- C语言程序创建文件夹
#include <stdio.h> #include <process.h> #include <dir.h> int main(void) { int stat ...
- 浅谈JavaScript中的cookie
什么是cookie?简单来说,cookie就是网站服务器存放在我们计算机上的一小段(一般大小不超过4KB)用来识别和记录用户的个人信息的文本.HTTP协议是一种没有“状态”的传输协议,也就是说,服务器 ...
- 第一课trie 树 POJ 2001
最短前缀(Openjudge上抄的) 总时间限制: 1000ms 内存限制: 65536kB 描述 一个字符串的前缀是从该字符串的第一个字符起始的一个子串.例如 "carbon"的 ...