交互式SQL和嵌入式SQL是SQL的两种使用方法。将SQL语言嵌入到宿主语言程序中,将SQL语言访问数据库的功能和宿主语言的数据处理功能相结合,这种使用SQL的方法称为嵌入式SQL。
数据库管理系统一般采用预编译方法处理,即由数据库管理系统的预处理程序对源程序进行扫描,识别出嵌入式SQL语句,把它们转换成主语言调用语句,以使主语言编译程序能识别它们,然后由主语言的编译程序将纯的主语言程序编译成目标码
为了调用,将SQL语言转变为函数调用
用EXEC SQL前缀来标识SQL语句,以区分宿主语言与SQL语言。
EXEC SQL <SQL语句>;
SQL负责操纵数据库,高级语言语句负责控制逻辑流程
数据库工作单元与源程序工作单元之间的通信主要包括:
描述当前的工作状态与运行环境 是一个数据结构 应用程序每执行完一条SQL语句之后都应该测试一下 SQLCODE的值,以了解该SQL语句执行情况并做相应处理
定义SQLCA:
Exec SQL Include SQLCA
SQL语言中使用的主语言程序变量简称为主变量
宿主语言与SQL语言之间通过共享变量进行数据传送
共享变量由宿主语言程序定义,可在SQL语句中引用。
输入主变量由应用程序对其赋值,SQL语句引用:输出主变量由SQL语句对其赋值或设置状态信息,返回应用程序。
所有主变量和指示变量必须在SQL语句 BEGIN DECLARE SECTION
与END DECLARE SECTION
之间进行说明。说明之后,主变量可以在SQL语句中任何一个能够使用表达式的地方出现。为了与数据库对象名(表名、视图名、列名等)区别,SQL语句中的主变量名和指示变量前要加冒号(:)作为标志。
查询结果为单个记录的,可以使用INTO子句指定存放查询结果的主变量
EXEC SQL SELECT Sno, Sname, Ssex, Sage, Sdept
INTO Hsno, Hname, Hsex, Hage, Dept
FROM Student WHERE Sno= givens;/把要查询的学生的学号赋给了主变量 givens
SQL是面向集合的,一条SQL语句可以产生或处理多条记录:而主语言是面向记录的,一组主变量一次只能存放一条记录。所以仅使用主变量并不能完全满足SQL语句向应用程序输出数据的要求。
游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果,每个游标区都一个名字。用户可以通过游标逐一获取记录并赋给主变量,交由主语言进一步处理
超过一行结果用游标,一行结果交给主变量
采用类似指针的技术定位某一个元组
定义游标:Exec SQL declare cursor <游标名> for <查询子句>; (说明性语句 实际并不执行查询子句)
打开游标:Exec SQL open <游标名>; (执行查询语句,将查询结果放到缓冲区,指针指向第一条记录)
推进游标:Exec SQL fetch <游标名> into <主变量表>;
关闭游标:Exec SQL close <游标名>;
建立连接的嵌入式SQL语句是
EXEC SQL CONNECT TO target[AS connection-namel【USER user-name];
target是要连接的数据库服务器 Connection-name是可选的连接名
关闭数据库连接的嵌入式SQL语句是
EXEC SQL DISCONNECT [connection];
其中, connection是 EXEC SQL CONNECT所建立的数据库连接。
EXEC SQL BEGIN DEC LARE SECTION; /*主变量说明开始*/
char deptname[64];
char HSno[64];
char HSname[64];
char HSsex[64];
int HSage;
int NEWAGE;
EXEC SQL END DECLARE SECTION; /*主变量说明结束*/
long SQLCODE;
EXEC SQL INCLUDE sqlca; /*定义SQL通信区*/
int main(void) /*C语言主程序开始*/
{
int count = 0;
char yn; /*变量yn代表yes或no*/
printf("Please choose the department name(CS/MA/IS): ");
scanf("%s", deptname); /*为主变量deptname赋值*/
EXEC SQL CONNECT TO TEST@localhost:54321 USER
"SYSTEM" /"MANAGER"; /*连接数据库TEST*/
EXEC SQL DECLARE SX CURSOR FOR /*定义游标SX*/
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) /* 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; /*关闭游标SX不再和查询结果对应*/
EXEC SQL COMMIT WORK; /*提交更新*/
EXEC SQL DISCONNECT TEST; /*断开数据库连接*/
}
DECLARE—可选部分
变量、常量、游标、用户定义异常的声明
……
BEGIN—必要部分
SQL语句和PL/SQL语句构成的执行程序
……
EXCEPTION—可选部分
程序出现异常时,捕捉异常并处理异常
……
END;—必须部分
CREATE TRIGGER <触发器名>
{ BEFORE | AFTER}
<触发事件> ON <表名>
FOR EACH {ROW | STATEMENT}
<触发动作体>;
定义一个BEFORE行级触发器,为教师表Teacher定义完整性规则“讲师的工资不得低于3000元,如果低于3000元,自动改为3000元”。
CREATE TRIGGER Insert_Or_Update_Sal
BEFORE INSERT OR UPDATE ON Teacher /*触发事件是插入或更新操作*/
FOR EACH ROW /*行级触发器*/
BEGIN /*定义触发动作体,是PL/SQL过程块*/
IF (new.Job=‘讲师') AND (new.Sal < 3000) THEN
new.Sal :=3000;
END IF;
END;
触发器的执行,是由触发事件激活的,并由数据库服务器自动执行。
一个数据表上可能定义了多个触发器。
同一个表上的多个触发器激活时遵循如下的执行顺序:
? 1. 执行该表上的BEFORE触发器;
? 2. 激活触发器的SQL语句;
? 3. 执行该表上的AFTER触发器;
(多个BEFORE执行顺序不相同)
触发器必须是一个已经创建的触发器,并且只能由具有相应权限的用户删除。
DROP TRIGGER <触发器名> ON <表名>;
如: DROP TRIGGER Insert_Sal ON Teacher;
函数与存储过程的区别是:函数必须指定返回的类型
过程化SQL块主要有两种类型,即命名块和匿名块。
存储过程:由过程化SQL编写的过程,经编译和优化后存储在数据库服务器中,使用时只要调用即可。
存储过程降低了客户机和服务器之间的通信量。客户机上的应用程序只要通过网络向服务器发出调用存储过程的名字和参数,就可以让关系数据库管理系统执行其中的多条SQL语句并进行数据处理。只有最终的处理结果才返回客户端
/*创建存储过程*/
Create [or replace] procedure 过程名
[(argument1 [in|out|in out] type1 , argument2 [in|out|in out] type2, ……)]
{IS | AS}
<类型、变量的说明>
Begin
<执行部分>
Exception
<可选的异常处理部分>
end;
/*创建函数*/
Create or replace function 函数名 [(argment [{in|out|in out}] type,…)]
Return return_type
{IS |AS}
<类型、变量说明>
Begin
<函数体,执行部分>
Exception
<可选的异常处理部分>
End;
示例:
/*修改成绩*/
create or replace procedure set_grade(sid sc.sno%type, cid sc.cno%type,
newgrade sc.grade%type, st out varchar2) is
begin
update sc set grade=newgrade where sno=sid and cno=cid;
st:='OK!';
commit;
exception
when no_data_found then
st:='数据不存在!';
when others then
st:='操作失败!';
end;
/*调用*/
declare
mm varchar2(20);
begin
set_grade('20140001','1001',90,mm);
dbms_output.put_line('操作结果:' || mm);
end;
事务是一系列的数据库操作,是数据库应用程序的基本逻辑单元。
不可分割的工作单位,恢复与并发控制的基本单位
一个事务就是将一系列的数据操纵SQL语句作为一个逻辑单元,逻辑单元里面的单个操作要么全做,要么全部不做,以保证数据的完整性。
一个事务可以是一条SQL语句,一组SQL语句或整个程序。一般来讲,一个程序包含多个事务。
事务的开始与结束可以用户显式的控制。不显式的定义,系统会自动划分。
BEGIN TRANSACTION: 事务开始
COMMIT; 提交事务的所有操作,事务正常结束
ROLLBACK;事务回滚,运行过程中对数据库的所有操作全部撤销,回滚到事务开始的状态
原子性
不可分割 所有操作要么都做 要么不做
一致性
事务执行的结果必须是从一个一致性状态到另一个一致性状态 操作要么全做 要么不做 数据库都处于一致的状态
隔离性
一个事务的执行不能被其他事务干扰,并发执行的各个事务不能互相干扰 锁技术
持续性
永久性 事务一旦提交,对数据库中数据的改变是永久性的。
原文:https://www.cnblogs.com/dingruihfut/p/11784452.html