本文仅供参考学习使用,谢谢
文章目录
- 从主语言访问数据库的基本步骤
- 1.建立数据库连接
- 2.定义主变量与数据通讯区
- 3.执行SQL语句
- 4.关闭数据库连接
- 嵌入式SQL语句的基本格式
- 嵌入式SQL语句与主语言之间的通信
- 1.SQL通信区
- 2.主变量
- 3.游标
- 查询结果为多条记录的SELECT语句
- 1.申明游标
- 2.打开游标
- 3.推进游标指针并取当前记录
- 4.关闭游标
- CURRENT形式的UPDATE/DELETE语句
从主语言访问数据库的基本步骤
- 打开数据库
- 定义必要的主变量和数据通信区
- 用SQL访问数据库,并对返回结果进行处理
- 关闭数据库
eg:
#include <stdio.h>
#include <stdlib.h>
EXEC SQL BEGIN DECLARE SECTION; /** 主变量说明开始*/
char HSno[9];
char HSname[20];
char HSex[2];
int HSage;
char Hdept[20];
EXEC SQL END DECLARE SECTION; /** 主变量说明结束*/
long SQLCODE;
EXEC SQL INCLUDE sqlca;/** 定义SQL通信区 */
int main() {
printf("Please input the sno:");/** 输入要查找的学生学号*/
scanf("%s", HSno);
/** 连接数据库(数据库名字是TEST,主集名字是localhost,端口号为54321,用户名密码为“SYSTEM/krms”*/
EXEC SQL CONNECT TO TEST@localhost:54321 AS CONN1 USER "SYSTEM“ USING “manager";
EXEC SQL
SELECT Sno,Sname,Ssex,Sage,Sdept INTO:Hsno,:Hname,:Hsex,:Hage,:Hdept
FROM Student
WHERE Sno=:HSno;
if (sqlca.sqlcode == 0) {
printf("\n% - 9s% - 20s% - 2s% - 4s% - 20s\n", "Sno", "Sname","Ssex", "Sage", "Sdept");
printf("% - 9s% - 20s% - 2s% - 4s% - 20s\n", Hsno, Hname, Hsex, HSage, Hdept);
}
EXEC SQL DISCONNECT CONN1;
return 0;
}
1.建立数据库连接
EXEC SQL CONNECT TO target
[AS connection-name]
[USER user-name];
- target是要链接的数据库服务器的名字
- 常见的服务器表示串,如@:
- 包含服务器标识的SQL串常量
- DEFAULT
- connect-name是可选的连接名
- 连接名必须是一个有效的标识符
- 在整个程序内只有一个连接时可以不指定连接名
- 程序运行过程中可以修改当前连接
EXEC SQL SET CONNECTION connection-name
|DEFAULT;
2.定义主变量与数据通讯区
EXEC SQL BEGIN DECLARE SECTION; /**主变量说明开始*/
char Deptname[20];
char Hsno[9];
char Hsname[20];
char Hssex[2];
int HSage;
int NEWAGE;
EXEC SQL END DECLARE SECTION; /**主变量说明结束*/
long SQLCODE;
EXEC SQL INCLUDE SQLCA; /*定义SQL通信区*/
3.执行SQL语句
- 所有的SQL语句都可以以嵌入式的方式使用
- DDL数据定义语言(CREATE)
- DML数据控制语言(GRANT,REVOKECOMMITROBACK)
- DCL数据更新语言(UPDATE, INSERT, DELETE)
- DQL数据查询语言 (SELECT)
eg:
//根据学生号码查询学生的信息
EXEC SQL SELECT Sno,Sname,Ssex,Sage,Sdept
INTO:Hsno,:Hname,:Hsex,:Hage,:Hdept
FROM Student
WHERE Sno=:givensno;
//增加了一个INTO子句,用于保存查询结果
//前面带有 “ : ” 标识的变量成为主变量,即主语言的变量
- INTO子句,WHERE子句和HAVING短语的条件表达式中均可以使用主变量
- 查询返回的记录中,可能存在某些列为空值NULL
- 注意:如果查询结果实际上并不是单条记录,而是多条记录,则程序出错,关系数据库管理系统会返回错误信息
- 在UPDATE的SET子句和WHERE子句中可以使用主变量
//修改某个学生选修1号课程的成绩
EXEC SQL UPDATE SC
SET Grade=:newgrade /*修改的成绩已赋给主变量:newgrade*/
WHERE Sno=:givensno AND Cno=1; /*学号赋给主变量:givensno*/
4.关闭数据库连接
EXEC SQL DISCONNECT [connection];
实例:
//打印指定学号的学生记录
//主变量定义区
EXEC SQL BEGIN DECLARE SECTION;
char Deptname[20];
char HSNo[9];
char HSName[20];
char HSSex[2];
int HSAge;
EXEC SQL END DECLARE SECTION;
//定义SQL通讯区
long SQLCODE;
EXEC SQL INCLUDE SQLCA;
//C语言主程序开始
int main(void){
printf("Please input the student number ");
scanf("%s", Hsno); //为主变量Hsno赋值
//连接Test数据库
EXEC SQL CONNECT TO TEST@localhost:54321 AS CONN1
USER "SYSTEM" USING "MANAGER"
//执行SQL查询
EXEC SQL SELECT Sno,Sname,Ssex,Sage,Sdept
INTO:Hsno,:Hname,:Hsex,:Hage,:Hdept
FROM Student
WHERE Sno=:HSno
//
if(sqlca.sqlcode == 0){ /* SQLCA中的SQLCODE == 0 表示操作成功*/
printf("\n %-9s %-20s %-2s %-4s %-20s\n", "Sno", "Sname", "Ssex", "Sage", "Sdept");
printf("% - 9s% - 20s% - 2s% - 4s% - 20s\n", Hsno, Hname, Hsex, HSage, Hdept);
}
EXEC SQL DISCONNECT CONN1;//关闭游标断开连接
嵌入式SQL语句的基本格式
- 为了区分SQL语句与诸语言语句,所有的SQL语句必须加前缀EXEC SQL
主语言为C语言时,语句格式:
EXEC SQL <SQL 语句>;
eg:
EXEC SQL SELECT Sno,Sname,Ssex,Sage,Sdept
INTO:Hsno,:Hname,:Hsex,:Hage,:Hdept
FROM Student
WHERE Sno=:givensno;
嵌入式SQL语句与主语言之间的通信
- 数据库工作单元与主程序工作单元之间的通讯
- 向主语言传递SQL语句的执行状态信息,使主语言能够据此控制程序流程
//主要用于SQL通信区实现 - 主语言向SQL语句提供参数
//主要用主变量实现 - 将SQL语句查询数据库的结果返回给主语言处理
//主要用主变量和游标实现
1.SQL通信区
- SQLCA的用途
- SQL语句执行后,系统反馈给应用程序信息
- 描述系统当前工作状态
- 描述运行环境
- 这些信息将送到SQL通讯区中
- 应用程序从SQL通信区中取出这些状态信息,据此决定接下来执行的语句
- SQLCA:SQL Communication Area
- SQLCA是一个数据结构
struct sqlca_t{
char sqlcaid[8];
long sqlabc;
long sqlcode;
struct{
int sqlerrml;
char sqlerrmc[SQLERRMC_LEN];
}sqlerrmc;
char sqlerrp[8];
long sqlerrd[6];
char sqlwarn[8];
char sqlstate[5];
};
SQLCA使用方法:
- 定义SQLCA
EXEC SQL INCLUDE SQLCA
- 使用SQLCA
- SQLCA中有一个存放每次执行SQL语句后返回代码的变量SQLCODE
- 如果SQLCODE等于与定义的常量SUCCESS,则表示SQL语句成功,否则出错
- 应用每执行完一条SQL语句之后都应该测试一下SQLCODE的值,以了解SQL语句执行情况并做相应处理
2.主变量
- 主变量
- 嵌入式SQL语句中可以使用主语言的程序变量来输入或输出数据
- 在SQL语句中使用的主语言程序变量简称为主变量(Host Variable)
- 主变量的类型
- 输入主变量
- 由应用程序对其赋值,SQL语句引用
- 输出主变量
- 由SQL语句对其赋值或设置状态信息,返回给应用程序
- 指示变量
- 是一个整型变量,用来“指示”所指主变量的值或条件
- 一个主变量可以附带一个指示变量(Indicator Variable)
- 指示变量的用途
- 指示输入主变量是否为空值
- 检测输出变量是否为空值,值是否被截断
eg1:
/*查询某个学生选修的某门课程的成绩,假设已经把将要查询的
学生学号赋给了主变量givensno
将课程号赋给了主变量givencno */
EXEC SQL SELECT Sno,Cno,Grade
INTO :Hsno,:Hcno,:Hgrade:Gradeid /* 指示变量Gradeid*/
FROM SC
WHERE Sno=:givensno AND Cno=:givencno
//如果Gradeid < 0Hgrade,不论Hgrade为何值,均认为该学生成绩为空
eg2:
//某个学生选修了某门课程,将有关记录插入SC表中,
//假设插入的学号已赋值给主变量stdno,课程号已赋值给主变量couno
gradeid=-1 /*gradeid为指示变量,赋值为负值*/
EXEC SQL INSERT
INTO SC(Sno,Cno,Grade)
VALUES(:stdno,:couno,:gr :gradeid);
//:stdno , :couno , :gr为主变量
//由于该学生刚选修课程,成绩应为空,所以要把指示变量赋值为负值
在SQL语句中使用主变量和指示变量的方法
- 说明主变量和指示变量
BEGIN DECLARE SECTION
...
... //在此说明
...
END DECLARE SECTION
- 使用主变量
- 说明之后的主变量可以在SQL语句中任何一个能够使用表达式的地方出现
- 为了与数据库对象名(表名,视图名,列名etc)区别,SQL语句中的主变量名前面要加冒号(:)作为标志
- 使用指示变量
- 指示变量前也必须加冒号标志
- 必须紧跟在所指主变量之后
- 在SQL语句之外(主语言语句中)使用主变量和指示变量的方法
- 直接使用不用加冒号
3.游标
游标的定义:
- 游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果
- 每个游标区都有一个名字,也可以理解为该数据区的指针
- 用户可以用SQL语句逐一从游标中(指针所指示的位置)获取记录,并赋给主变量,交由主语言进一步处理
为什么要使用游标:
- SQL语言与主语言具有不同数据处理方式
- SQL语言是面向集合的,一条SQL语句原则上可以产生或处理多条记录
- 主语言是面向记录的,一组主变量一次只能存放一条记录
- 仅使用主变量并不能完全满足SQL语句向应用程序输出数据的要求
- 嵌入式SQL引入了游标的概念,用来协调这两种不同的处理方式
使用游标的步骤:
- 说明游标(DECLARE)
- 打开游标(OPEN)
- 推进游标指针并取当前记录( FETCH )
- 关闭游标(CLOSE)
必须使用游标的SQL语句:
- 查询结果为多条记录的SELECT语句
- CURRENT形式的UPDATE语句
- CURRENT形式的DELETE语句
查询结果为多条记录的SELECT语句
1.申明游标
- 使用DECLARE语句
EXEC SQL DECLARE <游标名> CURSOR
FOR <SELECT语句>;
- 功能
是一条说明性语句,这时DBMS并不执行SELECT指定的查询操作。
2.打开游标
- 使用OPEN语句
EXEC SQL OPEN <游标名>;
- 功能
- 打开游标实际上是执行相应的SELECT语句,把所有满足查询条件的记录从指定表取到缓冲区中
- 这时游标处于活动状态,指针指向查询结果集中第一条记录
3.推进游标指针并取当前记录
- 使用FETCH语句
EXEC SQL FETCH [ [NEXT|PRIOR|FIRST|LAST] FROM ] <游标名>
INTO <主变量>[<指示变量>]
[,<主变量>[<指示变量>]]...;
NEXT|PRIOR|FIRST|LAST:指定推动游标指针的方式
NEXT:向前推进一条记录
PRIOR:向回退一条记录
FIRST:推向第一条记录
LAST:推向最后一条记录
默认缺省值为NEXT
- 功能
- 指定方向推动游标指针,然后将缓冲区中的当前记录取出来送至主变量供主语言进一步处理
4.关闭游标
- 使用CLOSE语句
EXEC SQL CLOSE <游标名>;
- 功能
- 关闭游标,释放结果集占用的缓冲区及其他资源
- 说明
- 游标被关闭后,就不再和原来的查询结果集相联系
- 被关闭的游标可以再次被打开,与新的查询结果相联系
删除游标:
DEALLOCATE <游标名>;
CURRENT形式的UPDATE/DELETE语句
CURRENT形式的UPDATE语句和DELETE语句的用途
面向集合的操作: 一次修改或删除所有满足条件的记录
- 如果只想修改或删除其中某个记录
- 用带游标的SELECT语句查出所有满足条件的记录
- 从中进一步找出要修改或删除的记录
- 用CURRENT形式的UPDATE语句和DELETE语句修改或删除之
- UPDATE语句和DELETE语句中的子句:
WHERE CURRENT OF <游标名>
表示修改或删除的是最近一次取出的记录,即游标指针指向的记录
- 不能使用CURRENT形式的UPDATE语句DELETE语句 :
- 当游标定义中的SELECT语句带有UNION或ORDER BY子句
- 该SELECT语句相当于定义了一个不可更新的视图
//依次检查某个系的学生记录,交互式更新某些学生年龄
EXEC SQL BEGIN DECLARE SECTION; //主变量说明开始
char Deptname[20];
char Hsno[9];
char Hsname[20];
char Hssex[2];
int HSage;
int NEWAGE;
EXEC SQL END DECLARE SECTION; //主变量说明结束
//定义SQL通信区
long SQLCODE;
EXEC SQL INCLUDE SQLCA;
int main(void){ //c语言主程序开始
int count = 0;
char yn; //变量yn代表 yes或no
printf("Please choose the department name(CS/MA/IS): ");
scanf("%s",deptname); //为主变量deptnumber赋值
EXEC SQL CONNECT TO TEST@localhost:54321 USER
"SYSTEM"/"MANAGER"; //连接数据库Test
EXEC SQL DECLARE SX CURSOR FOR //定义游标
SELECT Sno,Sname,Ssex,Sage //SX对应的语句
FROM Student
WHERE SDept = :deptname;
EXEC SQL OPEN SX; //打开游标SX,只想查询结果的第一行
for ( ; ; ) { //循环结构逐条处理结果集中的记录
EXEC SQL FETCH SX INTO :HSno,:Hsname,:HSsex,:HSage; //推进游标将当前数据放入主变量
if (SQLCA.SQLCODE!= 0) //SQLCA.SQLCODE!=0 表示操作不成功
break; //利用SQLCA中的状态信息决定何时退出循环
if(count++ == 0) //如果是第一行的话,先打出行头
printf("\n%-10s %-20s %-10s%-10s\n","Sno“,"Sname“,"Ssex", "Sage");
//打印查询结果
printf("%-10s %-20s %-10s %-10d\n",HSno,Hsname,Hssex,HSage);
printf("UPDATE AGE(y/n)?");//询问用户是否要更新该学生的年龄
do{scanf("%c",&yn);}
while(yn != 'N' && yn != 'n' && yn != 'Y' && yn != 'y');
if (yn == 'y' || yn == 'Y') { //如果选择更新操作
printf("INPUT NEW AGE:");
scanf("%d",&NEWAGE); //用户输入新年龄到主变量中
EXEC SQL UPDATE Student //嵌入式SQL更新语句
SET Sage = :NEWAGE
WHERE CURRENT OF SX;
}
}
EXEC SQL CLOSE SX; //关闭游标,不再和查询结果对应
EXEC SQL COMMIT WORK; //提交更新
EXEC SQL DISCONNECT TEST; //断开数据库连接
}