关系数据库标准语言SQL(二)

声明:最近在准备考试,故整理数据库原理笔记。

视图

视图的创建和删除

CREATE VIEW <视图名 > [ <列名 > , ……, <列名 >)] AS <查询表达式 >
[WITH CHECK OPTION]
视图名 对定义的视图命名
列名 为 查询表达式 结果的诸列命名
查询表达式 通常是一个 SELECT 查询
WITH CHECK OPTION 表示该视图是可更新的,并且对视图进行更新时要满足 <查询表达式> 的查询条件

行列子集视图

CREATE
VIEW SE_Students
AS
SELECT Sno, Sname, Sex, Birthday, Dno
FROM Students
WHERE Speciality = ‘软件工程'
WITH CHECK OPTION;

基于多个表的视图

CREATE VIEW Student_Grades (Sno , Sname , Cname),
AS SELECT S .Sno , Sname , Cname , Grade
FROM Students S , SC, Courses C
WHERE S .Sno = SC.Sno AND C .Cno = SC.Cno ;

基于视图的视图

CREATE VIEW CS_Student_Grades (Sno, Sname, Cname, Grade)
AS SELECT S.Sno, Sname, Cname, Grade
FROM Students S, Student_Grades SG
WHERE S.Sno = SG.Sno AND Speciality = ‘计算机科学与技术’;

基于聚集函数的视图

CREATE VIEW Student_Avg_Grades (Sno, Sname, Avg_Grade)
AS SELECT S.Sno, Sname, AVG (Grade)
FROM Students S, SC
WHERE S.Sno=SC.Sno
GROUP BY S.Sno, Sname;

视图删除

 DROP VIEW Student_Grades或
 DROP VIEW Student_Grades RESTRICT
 不能删除视图Student_Grades,因为视图CS_Student_Grades的定义依 赖于它
 DROP VIEW Student_Grades CASCADE
 将删除视图Student_Grades,并且级联地删除视图CS_Student_Grades

基于视图的查询

 查询软件工程专业的男生

SELECT *
FROM SE_Students
WHERE Sex= ‘男’;

等价于

SELECT *
            FROM (SELECT Sno, Sname, Sex, Birthday, Dno
                FROM Students
                WHERE Speciality = ‘软件工程’) 
        AS SE_Students (Sno, Sname, Sex, Birthday, Dno)
        WHERE Sex= ‘男’;

基于视图的更新

向软件工程专业学生的视图SE_Students中插入一个新的记录,学号为201805109,姓名为吴畅,出生年月1999-05-04,女性,所在院系EI

INSERT INTO SE_Students (Sno, Sname, Birthday, Sex, Dno)
VALUES (‘201805109’, ‘吴畅’, 1999-05-04, ‘女’, ‘EI’);

等价于

INSERT INTO Students (Sno, Sname, Birthday, Sex, Dno, Speciality)
VALUES (‘201805109’, ‘吴畅’, 1999-05-04, ‘女’, ‘EI’, ‘软件工程’);

删除软件工程专业学号为201805201的学生

DELETE FROM SE_Students
WHERE Sno=‘201805201’;

等价于:

DELETE FROM Students
WHERE Sno=‘201805201’ AND Speciality = ‘软件工程’;

不可更新视图

视图S_G为不可更新视图

 CREATE VIEW S_G (Sno,Gavg) 
 AS 
    SELECT  Sno,AVG(Grade) 
    FROM    SC 
    GROUP BY Sno;

视图的作用

使用视图可以 使一些查询表 达更加简洁
视图提供了一 定程度的逻辑 独立性
视图可以起到 安全保护作用
视图使得用户 能够以不同角 度看待相同的 数据

嵌入式SQL

为什么使用嵌入式SQL

 SQL是一种非过程语言,用SQL语言表达查询比用通用的程序设计语言编码简单得多
 我们在开发数据库应用系统时,很多时候需要使用通用程序设计语言访问数据库:
 一些非数据库操作,如打印报表、将查询结果送到图形用户界面中,都不能用SQL语句实现
 SQL能够表达常见的查询,但是不能表达所有查询

SQL语句的识别与处理

 当主语言源程序中嵌入SQL语句时,这种源程序已经不是纯的主语言源程序,通常的主语言编译系统不能处理这种源程序
 解决这一问题的方法有两种:
(1) 扩充主语言编译系统,使之能处理SQL语句
(2) 预处理:在编译前先扫描源程序,将SQL语句翻译成目标代码
 通常,商品化DBMS采用预处理方法,预处理程序由DBMS开发商提供
 例如,微软的SQL Server 2000 提供的预处理程序nsqlprep.exe
 为了能够区分源程序中的SQL语句和主语言语句,SQL规定:
 所有嵌入式SQL语句都必须加前缀EXEC SQL
 SQL语句的结束标志则因主语言的不同而异
当主语言是C语言时,嵌入式SQL语句的一般形式为:
EXEC SQL <SQL语句>;

与主语言通信

SQLCODE

 每个SQL语句执行执行之后需要反馈一些状态信息,系统将这些状态信息存入SQLCODE中  主语言语句可以访问SQLCODE,根据结果采取相应的动作
 SQLCODE是一个整型变量
 如果SQL语句成功执行,则SQLCODE=0
 如果执行结果无数据则SQLCODE=100
 其他情况为异常,SQLCODE取负值,其具体值依赖于实现

主语言

 SQL语句与主语言语句交换信息的另一种途径是使用主语言变量
 使用如下形式说明的主语言变量在主语言语句和SQL语句都能使用:
 EXEC SQL BEGIN DECLARE SECTION;
 主语言变量说明;
 EXEC SQL END DECLARE SECTION;
 SQL语句与主语言语句可以通过主语言变量交换信息
 SQL规定:SQL语句中出现的主语言变量之前必须加冒号(:)

指示变量

 SQL支持空值(NULL),但是主语言并无对应概念
 为了解决这一问题,嵌入式SQL引进了指示变量(indicator variable)
 指示变量是主语言的整型变量
 每个可能被SQL语句赋予空值的主变量都可以后随一个指示变量,用来指示对应的主变量是否为空值
 在SQL语句执行结束时,如果指示变量的值小于0,则其对应的主变量并未被赋值(可以视为空值)

游标

 为什么需要游标
 主语言是面向记录的,而SQL是面向集合
 存在矛盾:一个SQL语句得到的结果可能是多个记录,而主语言没有办法一次处理多个记录
 解决该问题的方法是使用游标
 游标其实就是一个数据缓冲区,暂时存放SQL语句的执行结果
 使用游标需要预先说明游标,在使用前打开游标,通过专门的SQL语句逐一提取记录,并在使用完之后关闭游标

连接数据库

 访问数据库前必须先建立数据库连接。SQL提供了建立和关闭数据库连接语句
 建立数据库连接的语句形式为:EXEC SQL CONNECT TO <SQL服务器>[AS <连接名>] [USER <用户名>];
 建立到当前服务器的默认连接:EXEC SQL CONNECT TO DEFAULT;
 关闭数据库连接的语句形式为:EXEC SQL DISCONNECTION <连接名>;

不使用游标的SQL语句

查询结果为单个记录的SELECT语句

 使用带INTO子句的SELECT语句将查询结果存放到主变量中
EXEC SQL SELECT <选择序列>
INTO <选择目标序列>
<其他子句>
 <选择目标序列>和<选择序列>包含相同个数的元素
 <选择目标序列>中的每个元素形如:
 :<主变量> [:<指示变量>]
 SQL执行有两种情况
 查询不成功:SQLCODE  0, 除了I/O错误之外,有两种情况导致查询不成功
 查询结果实际上并不是单条记录,而是多条记录
 满足查询条件的元组不存在
 查询成功:SQLCODE = 0

EXEC SQL SELECT Grade
INTO :Hgrade :igrade
FROM SC
WHERE Sno = :Hsno AND Cno = :Hcno;

非交互式更新

 某学生退学,需要删除他/她在Students中的登记和他/她的所有选课记录。假设该学生的学号已经赋予主变量Hsno,以下两个语句可
以完成删除工作:

EXEC SQL DELET FROM SC
        WHERE Sno=:Hsno;
EXEC SQL DELET FROM Students
        WHERE Sno=:Hsno;

 假设信工院全体学生的专业改为软件工程,软件工程已经赋予主变量Hspeciality。使用下面的程序可以修改学生的专业:

EXEC SQL UPDATE Students
SET Speciality=:Hspeciality
WHERE Dno=‘IE’;

使用游标的SQL语句

查询结果为多个元组的SELECT语句

 当查询结果为多个记录需要提交主语言程序处理时,可以查询语句说明一个只读游标
 打开游标就导致查询语句的执行
 主语言程序可以使用FETCH语句推进游标指针,取出每个查询结果进行处理
 最后,关闭游标
 查询某个院全体学生的信息(学号、姓名、性别和年龄),要查询的院系号由用户在程序运行过程中指定, 放在主变量Hdno中  对应的主变量定义如下:

EXEC SQL BEGIN DECLARE SECTION;
        char Hsno[9]; 
        char Hsname[8]; 
        char Hsex[2]; 
        int Hage; 
        char Hdno[10];
EXEC SQL END DECLARE SECTION;

实现该查询的程序段:

EXEC SQL DECLARE YX CURSOR FOR
        SELECT Sno, Sname, Ssex, Sage
        FROM Students
        WHERE Dno=:Hdno; 
EXEC SQL OPEN YX 
Hdno=’IE’;
WHILE(1) /* 用循环结构逐条处理结果集中的记录 */
{
        EXEC SQL FETCH YX
        INTO : HSno, : HSname, : HSsex, : HSage;
        if (sqlca.sqlcode <> 0) break; 
        …… /* 由主语言语句进行进一步处理 */
}
EXEC SQL CLOSE YX;

Current形式的更新语句

带CURRENT形式的UPDATE语句格式如下:
UPDATE T
SET A1 = e1, …, Ak = ek
WHERE CURRENT OF <游标名>
 其中T是基本表,游标定义在基本表T上,并且是可更新的
 A1, ..., Ak是T的属性,而e1, ..., ek是表达式

从Students和SC中删除某学生的记录的程序段如下:
char YN; // 变量YN不在SQL语句中使用
    EXEC SQL BEGIN DECLARE SECTION;
        char Givenname[8];
        char Hsno[9];
        char Hsname[8];
        char Hsex[2]; 
        char Henrollyear[4];
        char Hspeciality[20];
        char Hdno[4];
EXEC SQL END DECLARE SECTION;
EXEC SQL DECLARE Student_Cursor CURSOR FOR
    SELECT Sno, Sname, Sex, Enrollyear, Speciality, Dno 
    FROM Students
    WHER Sname=:Givenname
    FOR UPDATE;
Givenname= ‘李明’;
EXEC SQL OPEN Student_Cursor;
EXEC SQL FETCH Student_Cursor
    INTO :Hsno, :Hsname, :Hsex, :Henrollyear, Hspeciality, :Hdno;
while (SQLCODE= 0) {
    printf (‘%s %s %s %s %s %s \n’, Hsno, Hsname, Hsex, Henrollyear, Hspeciality, Hdno);/* 是否删除 */
printf("delete?(Y—delete,N—not delete): ");
scanf("%c\n",&YN);
if (YN=='y' || YN=='Y') {/* 删除SC元组,不用游标 */
EXEC SQL DELETE FROM SC
    WHERE Sno=:Hsno;/* 删除Students元组,使用游标 */
EXEC SQL DELETE FROM Students
    WHERE CURRENT OF Student_Cursor;/* 完成,退出 */
    break;
}
/* 取出下一位学生的信息 */
EXEC SQL FETCH Student_Cursor
    INTO :Hsno, :Hsname, :Hsex, :Henrollyear, Hspeciality, :Hdno;
}
/* 关闭游标 */
EXEC SQL CLOSE Student_ Cursor;

欢迎关注微信公众号:蛋炒番茄
同步分享资源、技术等!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342