本节讲述内容:

1.嵌入式SQL 语言概述

2.变量声明与数据库连接

3.数据集与游标

4.可滚动游标与数据库的增删改

5.状态捕捉以及错误处理机制

(一)嵌入式SQL语言

之前我们所学的都是交互式SQL 语言:  select .. from  .. where..

嵌入式SQL语言 表示 将SQL语言嵌入到 某一种高级语言中使用, 比如C++ ,Java, powerbuilder等

它们也称为宿主语言(host language).

复杂的检索不能用一条SQL语句完成, 需要结合高级语言中的顺序\分支\循环结构帮助处理.

if [conditon] then SQL_query else SQL_query   end if

do while [condition] SQL_query  end do

还有在SQL语句的检索结果基础上,再进行处理的

SQL_query1
for ... do
process the record
next
SQL_query 2
if .. then
else
end if

交互式SQL: select sname, sage from student where sname='xy';

嵌入式SQL: 以宿主语言C语言为例,

exec sql select sname, sage into :vsname, :vsage from student where sname='xy';

主要区别:

(1) exex sql 是一个引导词, 它引导sql 语句,  将SQL语句预编译成C编译器可识别的语句.

(2) 增加 into 子句, 用于把SQL 语句的检索结果赋给高级语言的程序变量

(3) 用冒号开头 表示高级语言的程序变量  :vsname  , :vsage

冒号很重要, 用于区分是程序变量 还是 表的字段!!  ....  还有很多特点之后在详细介绍

为啥要学嵌入式SQL , 用来解决啥问题?

下面逐个解决上述8个问题

(一) 数据库的连接(问题1)

在嵌入式SQL 操作之前, 首先需要与数据库进行连接

不同的DMBS 的语句是有差别的,

在嵌入式SQL程序执行之后, 需要断开数据库

SQL 执行的提交与撤销

SQL语句在执行过程中, 必须要有提交, 撤销语句

提交: exec sql commit work;

撤销: exec sql rollback work;

很多DBMS 都设计了捆绑 提交\撤销 与断开连接在一起的语句, 以保证在断开连接之前

使用户确认提交或 撤销先前的工作, Oracle 中就是这样:

exec sql commit release;

exec sql rollback release;

为什么需要提交和撤销呢? 这个设计到数据库中的'' 事务 ''处理

什么是事务?  从应用程序员角度来看, 事物是一个存取或者改变数据库内容的程序的一次执行,

或者说是一条或者多条SQL 语句的一次执行被看做是一个事务

事务 一般由应用程序员提出, 因此有开始和结束, 结束前需要提交或者撤销

begin transaction
exec sql...
exec sql...
exec sql commit work | exec sql rollback work --提交或者撤销
end transaction

注意: 提交表示这一系列操作对数据库的更新是有效的, 撤销则表示无效

其实从 任何一个SQL语句执行 就表示了一个事务的开始, 到了 commit  或 rollback 则结束一个事务,

因此上述的 begin end 可以省略.

事务的ACID 特性

A : atomicity 原子性, DBMS保证表示事务中的一组操作是不可分的,要么全做,要么一条也不做

C : consistency 一致性,例如两个人同时在买车票,会不会买到同一张车票

I: isolation  隔离性 两个事务操作互不干扰

D: durability  已提交事务的影响是持久的, 被撤销的事务影响可以恢复

事务处理技术是DBMS的核心处理技术!!

(二) 变量声明(问题2)

exec sql select sname, sage into :vsname, :vsage from student where sname=:specname;

加了冒号表示高级语言的程序变量,  这些变量需要声明

exec sql begin declare section; --开始声明
char vsname[], specname[] ='xy' ;
int vsage;
exec sql end declare section; -- 结束声明

注: 宿主程序的字符串变量长度要比字符型字段多1, 因为宿主程序的字符串尾部多一个终止符'\0' .

-- 变量的声明与使用

exec sql begin declare section;
char vsname[], specname[] ='xy' ;
int vsage;
exec sql end declare section;
-- 用户在此处 可以基于键盘输入给specname 赋值
exec sql select sname, sage into :vsname, :vsage from student where sname=:specname;

实例:  数据库连接+变量定义

#include<stdio.h>
#include"prompt.h"
exec sql include sqlca; --sqlca 表示SQL的通信区, communication area char cid_prompt[]="please enter customer id:";
int main()
{
exec sql begin declare section; --下面声明变量
char cust_id[], cust_name[];
float cust_discnt;
exec sql end declare section; exec sql whenever sqlerror goto report_error;-- 错误捕获
exec sql whenever not found goto notfound; -- 记录没有找到 strcpy(user_name,"poneilsql");-- 字符串赋值
strcpy(user_pwd,"123456"); exec sql connect :user_name identified by :user_pwd; -- 连接数据库
while((prompt(cid_prompt,1,cust_id,4))>=0){
exec sql select cname,discnt into :cust_name,:cust_discnt
from customers where cid=:cust_id; -- 根据输入的客户id 找到名字和折扣 exec sql commit work;-- 提交
printf("customer's name is %s and discount
is %.1f\n",cust_name, cust_discnt);
continue; -- 接着循环,再输入客户id
notfound:printf("can't find customer %s, continuing\n", cust_id);}
exec sql commit release; -- 断开数据库的连接
return 0;
report_error: -- 前面报错的执行
print_dberror();
exec sql rollback release; -- 断开连接
return 1;
}

(三) 数据集与游标(问题3 4 5)

问题3: SQL 语句如何执行?

问题4: 如何将SQL 检索到的结果传递回宿主程序进行处理?

问题5: 如何将静态SQL , SQL语句中的常量更换为变量?

如何读取单行数据和多行数据, 单行结果处理与多行结果处理的差异: into 子句 和 游标 cursor

1. 检索单行结果, 可以将结果直接传送到宿主主程序的变量中, select ... into ...

exec sql select sname, sage into :vsname, :vsage from student
where sname=:specname;

2. 如果是多行结果, 则需要使用游标cursor

游标是指向某个检索记录的指针, 通过这个指针, 每次读一行, 处理一行,

接着再读一行...,直到全部处理完毕  fetch..into... (一次一行)

需要先定义一个cursor-->再打开-->接着一条一条处理-->最后关闭

exec sql delcare cur_student cursor for  --游标名
select sno, sname, sclass from student
where sclass=''; -- 定义游标
exec sql open cur_student; --打开游标
exec sql fetch cur_student into :vsno, :vsname, :vsclass; --取数据
...
exec sql close cur_student; --关闭游标

具体实例:

已知表orders(cid, aid, product, dollars)  客户id, 代理人id, 产品, 金额

游标: 给定一个客户id, 选出该客户下的所有代理商 和 金额(多行数据)

#define True 1
#include<stdio.h>
#include"prompt.h"
exec sql include sqlca; --sqlca 表示SQL的通信区, communication area exec sql begin declare section; --声明变量
char cust_id[], agent_id[];
double dollar_sum;
exec sql end declare section; int main()
{
char cid_prompt[]="please enter customer id:"; -- 定义提示字符串
exec sql declare agent_dollars cursor for -- 定义游标
select aid,sum(dollars) from orders
where cid=:cust_id group by aid; exec sql whenever sqlerror goto report_error;-- 错误捕获
exec sql connect to testdbl; --连接数据库
exec sql whenever not found goto finish; -- 记录没有找到 while((prompt(cid_prompt,1,cust_id,4))>=0){
exec sql open agent_dollars; -- 打开游标
while(True){ -- 打印每一条记录
exec sql fetch agent_dollars into :agent_id,:dollar_sum;
printf("%s %11.2f\n",agent_id, dollar_sum)
}; finish:
exec sql close agent_dollars; -- 关闭游标
exec sql commit work; -- 提交
exec sql disconnect current;--断开连接
return 0;
report_error: -- 前面报错的执行
print_dberror();
exec sql rollback;-- 撤销
exec sql disconnect current; --断开连接
return 1;
}

总结游标:

exec sql delcare cur_student cursor for  --游标名
select sno, sname, sclass from student
where sclass=:vclass; -- 定义游标
order by sno
for read only; --只读, 不可更新

cursor 数据读取 fetch : exec sql fetch cursor_name into host_variable

exec sql delcare cur_student cursor for  --游标名
select sno, sname, sclass from student
where sclass=:vclass; -- 定义游标
order by sno
for read only; --只读, 不可更新
exec sql open cur_student; -- 打开
exec sql fetch cur_student into :vsno, :vsname, :vsage; -- 使用
exec sql close cur_student; -- 关闭

可滚动游标与数据库的增删改

标注的游标 始终是自开始到结束方向移动的, 每fetch 一次,向结束方向移动一次,

每一条记录只能被访问一次, 再次访问该记录只能关闭游标后重新打开

可不可以实现游标的向上移动呢? ODBC (open database connectivity) 是一种跨DBMS

的DB 操作平台, 它在应用程序与实际的DBMS之间提供了一种通用的接口,

很多DBMS不支持可滚动游标, 但是通过ODBC 可实现该功能

定义中增加了 scroll

使用如下:

可滚动游标移动时需要判断 是否到了结束位置, 或者到了起始位置,

EOF表示最后一条记录的后面位置

BOF表示起始位置的前面

如果不需要区分最上 最下, 则可以用whenever not found 进行检测

用游标进行数据库的增删改

1. 查找删除(与交互式delete 语句相同)

exec sql delete from customers c where c.city='harbin' and
not exists (select * from orders o where o.cid=c.cid)
-- 删除 城市是哈尔滨 且在订单 orders表里面没有记录的.

2. 定位删除

exec sql declare delcust cursor for
select cid from customers c where c.city='harbin' and
not exists (select * from orders o where o.cid=c.cid)
for update of cid;
exec sql open delcust
while(True){
exec sql fetch delcust into :cust_id;
exec sql delete from customers where current of delcust;}

1. 查找更新

exec sql update student s
set scalss='' where s.sclass='';

2.定位更新

exec sql declare stud cursor for
select * from student s where s.sclass='' and
for update of sclass;
exec sql open stud
while(True){
exec sql fetch stud into :vsno, :vsname,:vsclass;
exec sql update student
set sclass='' where current of stud;}

插入语句

exec sql insert into student(sno,sname,sclass)
values ('','xy',''); exec sql insert into master_stud(sno,sname,sclass)
select sno,sname,sclass from student;

综合实例: 求数据库中某一列位于中值的那一行

--已知表 orders(cid,aid,product,dollars)
-- 寻找数据库中某一列位于中值的那一行
#include<stdio.h>
#include"prompt.h"
exec sql include sqlca; --sqlca 表示SQL的通信区, communication area
char cid_prompt[]="please enter customer id:"; -- 定义提示字符串 int main()
{
exec sql begin declare section; --声明变量
char cid[], user_name[], user_pwd[];
double dollars; int ocount;
exec sql end declare section; exec sql declare dollars_cursor cursor for -- 定义游标
select dollars from orders
where cid=:cid and dollars is not null order by dollars; exec sql whenever sqlerror goto report_error;-- 错误捕获
strcpy(user_name,"poneilsql");-- 字符串赋值
strcpy(user_pwd,"123456");
exec sql connect :user_name identified by :user_pwd; -- 连接数据库
--exec sql whenever not found goto finish; -- 记录没有找到 while((prompt(cid_prompt,1,cust_id,4))>=0){
exec sql select count(dollars) into :ocount from orders
where cid=:cid;
if(ocount==0)
{printf("no record reviewed for cid value %s\n",cid);
continue;} exec sql open dollars_cursor;
for (i=0;i<(ocount+1)/2;i++)
exec sql fetch dollars_cursor into :dollars ;
exec sql close dollars_cursor;
exec sql commit work; -- 提交
printf("median dollar amount=%f\n",dollars); }

SQL入门(4): 嵌入式SQL语言的更多相关文章

  1. C语言中嵌入式SQL语句

    原文:[转载]C语言中嵌入式SQL语句 http://blog.csdn.net/cnlht/archive/2007/12/12/1930960.aspx原文地址 实验内容: 掌握SQL Serve ...

  2. 第14讲:嵌入式SQL语言(基本技巧)

    一.交互式SQL的局限 & 嵌入式SQL的必要性 专业人员(如DBA)可以熟练地运用交互式SQL语言,但普通用户却不是那么容易上手,所以需要通过数据库应用程序来使用数据库.编写一个可以与数据库 ...

  3. 数据库-第八章 数据库编程-8.1 嵌入式SQL

    嵌入式SQL 一.嵌入式SQL的处理过程 1.嵌入式SQL语句的基本格式 2.嵌入式SQL的处理过程 3.主语言访问数据库的基本步骤 ⅰ建立数据库连接 ⅱ定义必要的主变量和数据通信区 ⅲ访问数据库并返 ...

  4. .Net程序员学用Oracle系列(28):PLSQL 之SQL分类和动态SQL

    1.SQL 语句分类 1.1.分类方法及类型 1.2.数据定义语言 1.3.数据操纵语言 1.4.其它语句 2.动态 SQL 理论 2.1.动态 SQL 的用途 2.2.动态 SQL 的语法 2.3. ...

  5. 数据库原理及应用-SQL数据操纵语言(Data Manipulation Language)和嵌入式SQL&存储过程

    2018-02-19 18:03:54 一.数据操纵语言(Data Manipulation Language) 数据操纵语言是指插入,删除和更新语言. 二.视图(View) 数据库三级模式,两级映射 ...

  6. 数据库系统学习(十)-嵌入式SQL语言之动态SQL

    第十讲 嵌入式SQL语言之动态SQL 静态SQL 区别变量和属性:高级语言向嵌入式SQL传递变量的方法 动态SQL 动态构造SQL语句是应用程序员必须掌握的重要手段 SQL语句的动态构造示例 根据界面 ...

  7. 数据库系统学习(九)-嵌入式SQL语言之基本技巧

    第九讲 嵌入式SQL语言之基本技巧 901 什么是嵌入式SQL语言 交互式SQL语言的局限性 嵌入式SQL语言 交互式和嵌入式语言的对比 高级语言中使用嵌入式语言需要解决的问题 902 程序与数据库连 ...

  8. SQL入门经典(一)之简介

    今天是我第一天开通博客,也是我的第一篇博客.以后为大家带来第一篇关于学习技术性文章,这段时间会为大家带来是SQL入门学习.希望大家坚持读下去,因为学历有限.我也是初学者.语言表达能力不好和知识点不足, ...

  9. 3.7 嵌入式SQL

    可以放入所有高级语言中去,如C 因为,SQL是过程性语句,需要高级语言的非过程性处理集合的分类处理 一.一般形式 所有的SQL语句都必须加前缀EXEC SQL SQL语句完成结束标志(:或END EX ...

随机推荐

  1. 好久好久没写,,百度API逆地址解析以及删除指定marker

    百度地图Api中 除覆盖物有两个方法:map.removeOverlay()或者 map.clearOverlays(),其中 clearOverlays()方法一次移除所有的覆盖物removeOve ...

  2. LODOP、C-Lodop简短排查语句

    https使用,故障:1.是https网站吗,https扩展版C-Lodop如何使用 参考http://www.c-lodop.com/faq/pp32.html2.双击桌面上的c-lodop快捷方式 ...

  3. 微言netty:不在浮沙筑高台

    1. 写作缘起 几年前,我在一家农业物联网公司,负责解决其物联网产品线.我们当时基于.net平台打造了一套实时数据采集系统,可以把数以百万级的传感器传送回来的数据采集入库并根据这些数据进行建模.在搭建 ...

  4. [BZOJ 3745] [COCI 2015] Norma

    Description 给定一个正整数序列 \(a_1,a_2,\cdots,a_n\),求 \[ \sum_{i=1}^n\sum_{j=i}^n(j-i+1)\min(a_i,a_{i+1},\c ...

  5. Java大小写转化

    java大写转小写 public String toLowerCase(String str){ char[] chars = str.toCharArray(); for (int i = 0; i ...

  6. 题解 UVA1567 【A simple stone game】

    题目大意 一堆石子有n个,首先第一个人开始可以去1~

  7. SyntaxError: Unexpected token ' in JSON at position 2

    js中字符串转json对象时报错: Uncaught SyntaxError: Unexpected token s in JSON at position 2 解决方法: js中获取jsp的返回值 ...

  8. CMDB资产管理系统开发【day26】:admin action

    本节目标 审核写到数据库,我就单独写一个如下的 页面 单机go后就跳转到如下图界面,我们这节课的目标就是写一个这样的页面 asset\admin.py部分代码 注释如下: class NewAsset ...

  9. C++回顾day02---<继承相关问题>

    一:继承和组合混搭时,构造和析构调用原则 (一)先构造父类,再构造成员变量,最后构造自己 (二)先析构自己,再析构成员变量,最后父类析构(方向与构造相反) class A { public: int ...

  10. phpstorm快捷键大全

    前言:这段时间换了编辑器,所以挺多命令也改变了 转载来自:https://www.jianshu.com/p/ffb24d61000d?utm_campaign=maleskine&utm_c ...