SQL 语言 - 数据库系统原理
SQL 发展历程
从 1970 年美国 IBM 研究中心的 E.F.Codd 发表论文到 1974 年 Boyce 和 Chamberlin 把 SQUARE 语言改为 SEQUEL 语言,到现在的 SQL2、SQL3,SQL 一直都在不断完善和发展之中。SQL(结构化查询语言)虽然名为查询,但实际上具有定义、查询、更新和控制等多种功能。
SQL 数据库的体系结构
SQL 数据库的体系结构也是三级结构,但术语与传统关系模型术语不同,在 SQL 中,关系模式称为“基本表”,存储模式称为“存储文件”,子模式称为“视图”,元组称为“行”,属性称为“列”。
- SQL 数据库体系的结构要点如下:
- 一个 SQL 模式是表和约束的集合。
- 一个 SQL 表由行集构成,行是列的序列,每列对应一个数据项。
- 表有三种形式:基本表(实际存储在数据库中的表),导出表(执行了查询时产生的表),视图(若干基本表或其它视图构成的表的定义)。
- 一个基本表可以跨一个或多个存储文件,一个存储文件也可以放一个或多个基本表。存储文件与物理文件对应。
- 用户可以用 SQL 语句对视图和基本表进行查询等操作。
- SQL 的用户可以是应用程序,也可以是终端用户。
SQL 的组成
- SQL 由四部分组成:
- 数据定义语言(SQL DDL):定义 SQL 模式、基本表、视图、索引。
- 数据操纵语言(SQL DML):包括数据查询和数据更新。
- 数据控制语言(SQL DCL):包括对基本表和视图的授权、完整性规则的描述、事务控制等。
- 嵌入式 SQL 的使用规定。
SQL 的数据定义
- SQL 模式的创建和撤销
SQL 模式的创建可简单理解为建立一个数据库,定义了一个存储空间,其句法是:CREATE SCHEMA <模式名> AUTHORIZATION <用户名>。
撤销 SQL 模式的句法为:DROP SCHEMA <模式名> [ CASCADE | RESTRICT ],CASCADE 表示级联式方式,执行时将模式下所有基本表、视图、索引等元素全部撤销;RESTRICT 表示约束式,执行时必须在 SQL 模式中没有任何下属元素时方可撤销模式。
“模式”这个名词学术味太重,大多数 DBMS 中不愿采用这个名词,而是采用“数据库”,而语句采用 CREATE DATABASE 和 DROP DATABASE。
SQL 的基本数据类型
- 数值型:integer、smallint、real、double、precision、float(n)、numeric(p,d) 或 decimal(p,d)。
- 字符串型:char(n)、varchar(n),前者定长,后者变长。
- 位串型:bit(n)、bit varying(n),同上。
- 时间型:date、time。
各类型的值可以进行比较操作,但算术操作只限于数值型。两个日期类型的差是时间间隔类型(INTERVAL),日期加或减去 INTERVAL 可得到另一个日期。
基本表的创建、修改、撤销
下面是基本表的创建,其中,完整性约束包括主键子句(PRIMARY KEY)、检查子句(CHECK)、外键子句(FOREIGN KEY):
CREATE TABLE T
(
T# CHAR(4) NOT NULL,
TNAME CHAR(8) NOT NULL,
TITLE CHAR(10),
PRIMARY KEY (T#)
)
CREATE TABLE C
(
C# CHAR(4) NOT NULL,
CNAME CHAR(8) NOT NULL,
T# CHAR(10),
PRIMARY KEY (C#),
FOREIGN KEY (T#) REFERENCES T(T#)
)
基本表的修改句法如下,需注意,新增的列不能定义为 NOT NULL。
ALTER TABLE <基本表名> ADD <列名> <类型>
ALTER TABLE <基本表名> DROP <列名> [ CASCADE | RESTRICT ]
ALTER TABLE <基本表名> MODIFY <列名> <类型>
DROP TABLE <基本表名> [ CASCADE | RESTRICT ]
索引的创建和撤销:
CREATE [UNIQUE] INDEX <索引名> ON <基本表名> (<列名序列> [ASC][DESC])
DROP INDEX <索引名>
SQL 的数据查询
- SELECT 语句完整的句法:
SELECT <列名表(逗号隔开)> FROM <基本表或视图> [ WHERE <行条件表达式> ] [ GROUP BY <列名序列> ] [ HAVING <组条件表达式> ] [ ORDER BY < 列名 [ ASC | DESC ]> ]
- SELECT 语句中的限制和规定:
- 要求输出表格中不出现重复元组,则在 SELECT 后 加 DISTINCT 选项。
- 星号 * 是对于在 FROM 子句中命名表的所有列的简写。
- 列表达式是对于一个单列求聚合值的表达式。
- 表达式中允许出现加减乘除及列名、常数的算术表达式。
- 同一基本表在 SELECT 语句中多次引用时 用 AS 来增加别名。
- 查询结构的结构完全一致时,可以将两个查询进行并(UNION)、交(INTERSECT)、差(EXCEPT)操作。
- WHERE 子句可以用 BETWEEN … AND … 限定一个值的范围。
- WHERE 子句中字符串匹配用 LIKE 和百分号、下划线。
- 查询空值操作时用 IS NULL 来测试。
- 集合成员比较用 IN / NOT IN,集合成员算术比较用 <元组> θ SOME | ALL | ANY。
- 嵌套查询的改进写法:
- 导出表的使用:如果在 FROM 子句中使用子查询,则要给子查询的结果起个表名和相应的列名。
- WITH 子句和临时视图:SQL3 允许用户用 WITH 子句定义一个临时视图(即子查询),置于 SELECT 语句的开始处。而临时视图本身是用 SELECT 语句定义的。
- 例题:对于教学数据库的三个基本表如下,试用 SQL 的查询语句表达下列查询:
- S(S#,SNAME,AGE,SEX)
- SC(S#,C#,SCORE)
- C(C#,CNAME,TEACHER)
(1)检索学号为 S3 的学生所学课程的课程名与任课教师名。
SELECT CNAME,TEACHER FROM C WHERE C# IN (SELECT C# FROM SC WHERE S# = 'S3')
SELECT CNAME,TEACHER FROM SC,C WHERE SC.C# = C.C# AND S# = 'S3'
(2)检索至少选修 LIU 老师所授课程中一门课程的女学生姓名。
SELECT SNAME FROM S WHERE SEX = '女' AND S# IN (SELECT S# FROM SC WHERE C# IN (SELECT C# FROM C WHERE TEACHER = 'LIU'))
SELECT SNAME FROM S,SC,C WHERE SEX = '女' AND S.S# = SC.S# AND SC.C# = C.C# AND TEACHER = 'LIU'
(3)检索 WANG 同学不学的课程的课程号。
SELECT C# FROM C WHERE C# NOT IN (SELECT C# FROM SC WHERE S# = (SELECT S# FROM S WHERE SNAME='WANG'))
(4)检索至少选修两门课程的学生学号。
SELECT S# FROM SC GROUP BY S# WHERE COUNT(S#) >= 2
SELECT DISTINCT S# FROM SC AS X, SC AS Y WHERE X.S# = Y.S# AND X.C# != Y.C#
(5)检索全部学生都选修的课程的课程号与课程名。
SELECT C#,CNAME FROM C WHERE C.C# IN (SELECT C# FROM SC GROUP BY C# WHERE COUNT(C#) = SELECT COUNT(S#) STUCOUNT FROM S GROUP BY S#)
SELECT C#,CNAME FROM C WHERE NOT EXISTS (SELECT * FROM S WHERE NOT EXISTS (SELECT * FROM SC WHERE S# = S.S# AND C# = C.C#))
SQL 的数据更新
- 数据插入
INSERT INTO <基本表名> [(<列名序列>)] VALUES (<元组值>) // 注:元组值可以连续插入
INSERT INTO <基本表名> [(<列名序列>)] <SELECT 查询语句>
- 数据删除
DELETE FROM <基本表名> [ WHERE <条件表达式>]
- 数据更新
UPDATE <基本表名> SET <列名>=<值表达式>, [ <列名>=<值表达式> ] [ WHERE <条件表达式> ]
视图
- 视图的创建
CREATE VIEW <视图名> (<列名序列>) AS < SELECT 查询语句 >
- 视图的撤销
DROP VIEW <视图名>
- 视图的更新
对视图(虚表)的查询与基本表一致,但更新操作受到下面三条规则的限制:
- 如果视图是从多个基本表使用连接操作导出的,则不允许更新。
- 如果导出的视图使用了分组和聚合操作,不允许更新。
- 如果视图是从单个基本表只使用选择和投影操作导出的,且包括了基本表的主键或某个候选键,则可以执行更新操作。(这就相当于在基本表上操作)
嵌入式 SQL
- SQL 语言的使用方式:
在主语言(如C,Java,C# 等)中使用的 SQL 结构称为 嵌入式 SQL。在终端交互方式下使用,称为 交互式 SQL。
存储设备商的数据库是用 SQL 语句存取的,数据库和主语言程序间信息的传递是通过共享变量实现的,这些共享变量要用 SQL 的 DECLARE 语句说明。SQL2 规定,SQL_STATE 是一个特殊的共享变量,起着解释 SQL 语句执行状况的作用。它由 5 个字符组成,当一个 SQL 语句执行成功时,系统自动给它赋上全零值(“00000”)表示未发生错误;否则其值为非全零,表示发生的各种错误情况。程序可以根据 SQL_STATE 的值转向不同的分支,以控制程序的流向。
- 嵌入式 SQL 的实现方式:
- 扩充主语言的编译程序,使之能处理 SQL 语句。
- 采用预处理方式。(多数系统采用这种方式)
- 嵌入式 SQL 的使用规定:
- 在程序中区分 SQL 语句与主语言语句。SQL 语句前加前缀 EXEC SQL,并以 END_EXEC 作为结束标志(结束标志在不同的主语言中不同)。
- 允许嵌入的 SQL 语句引用主语言的程序变量。这些变量前需要加冒号“:”作前缀标识,并由 SQL 的 DECLARE 语句说明。
- SQL 的集合处理方式与主语言单记录处理方式之间的协调。需要用游标(cursor)机制,把集合处理转换成单记录处理方式。
例如,在 C 语言中可用下列形式声明共享变量。下面四行组成一个说明节,3 个共享变量,SQL_STATE 长度是 6 而不是 5 是因为 C 语言规定字符串变量值应有结束符 “\0”。
EXEC SQL BEGIN DECLARE SECTION;
CHAR sno[5], name[9];
CHAR SQL_STATE[6];
EXEC SQL END DECLARE SECTION;
嵌入式 SQL 的使用技术
SQL DDL 语句,只要加上前缀 EXEC_SQL 和结束标志 END_EXEC 就能嵌入在主语言中使用。但 SQL DML 语句在嵌入使用时,要注意是否使用了游标机制。
- SQL DML 语句的嵌入使用(不涉及游标)
由于增删改语句不返回数据结果,因此只需要加上前后缀就可以在主语言中使用。而对于 SELECT 语句,如果已知查询结果是单元组时,在加上前后缀后,还应再增加一个 INTO 子句,指出找到的值应送到共享变量中去。
例1. 在基本表 S 中,根据共享变量 givensno 的值检索学生的姓名、年龄、性别。“:”作为共享变量的前缀,与数据库中变量的作区别。程序已预先给出 givensno 的值,而 SELECT 查询结果将送到变量 sn、sa、ss 中。
EXEC SQL SELECT sname, age, sex INTO :sn, :sa, :ss FROM s WHERE s# = :givensno;
例2. 在基本表 S 中插入一个新学生,诸属性值已在共享变量中。
EXEC SQL INSERT INTO s (s#, sname, age) VALUES (:givesno, :sn, :sa);
例3. 根据学生的姓名共享变量 sn,删除一个学生的成绩。
EXEC SQL DELETE FROM SC WHERE s# = (SELECT s# FROM S WHERE SNAME = :sn);
例4. 把课程名为 MATHS 的成绩增加某个值,该值在 raise 中已给出。
EXEC SQL UPDATE SC SET SCORE = SCORE + :raise WHERE C# = (SELECT C# FROM C WHERE CNAME = 'MATHS');
- SQL DML 语句的嵌入使用(涉及游标)
当查询结果是多个元组时,此时主语言程序无法使用,一定要使用游标机制把多个元组一个一个地传送给主语言程序使用。
具体过程:
- 先定义一个游标与某个 SELECT 语句对应。
- 游标用 OPEN 语句打开后,处于活动状态,此时,游标指向查询结果第一个元组之前。
- 每执行一次 FETCH 语句,游标指向下一个元组,并把其值送到共享变量,供程序处理。如此反复,直到所有查询结果处理完毕。
- 最后使用 CLOSE 语句关闭游标。关闭的游标可以被重新打开,与新的查询结果相联系,但在没有被打开后前,不能使用。
例1. 在基本表 SC 中检索某学生(学号由共享变量 givensno 给出)的学习成绩信息(S#, C#, SCORE)。
#define NO_MORE_TUPLES ! (strcmp (SQLSTATE, "02000"))
void sel()
{
EXEC SQL BEGIN DECLARE SECTION;
char sno [5], cno [5], givensno [5];
int g;
char SQL_STATE [6];
EXEC SQL END DECLARE SECTION;
scanf ("%s", givensno);
EXEC SQL DECLARE scx CURSOR FOR
SELECT S#, C#, SCORE FROM SC WHERE S# = :givensno;
EXEC SQL OPEN scx;
while(1)
{
EXEC SQL FETCH FROM scx INTO :sno, :cno, :g;
if (NO_MORE_TUPLES) break;
print("%s, %s %d", sno, cno, g);
}
EXEC SQL CLOSE scx;
}
卷游标的定义和推进
之前的游标在推进时只能一行行推进,且不能返回,这给使用带来了一定的麻烦。SQL2 提供了卷游标(scroll cursor)技术解决这个问题,卷游标可以进退自如。
- 卷游标的定义语句
EXEC SQL DECLARE scx SCROLL CURSOR FOR <SELECT 子句>
- 卷游标的推进句法:NEXT(进一行)、PRIOR(退一行),FIRST(定位到查询结果第一行),LAST(定位到查询结果最后一行),RELATIVE n(n 可为正负数,表示相对当前游标位置,推进或后退 n 行),ABSOLUTE n(绝对定位,正数表示查询结果从上往下第 n 行,负数表示从下往上第 n 行)。
EXEC SQL FETCH NEXT FROM <游标名> INTO <变量表>
EXEC SQL FETCH PRIOR FROM <游标名> INTO <变量表>
EXEC SQL FETCH LAST FROM <游标名> INTO <变量表>
EXEC SQL FETCH RELATIVE -3 FROM <游标名> INTO <变量表>
EXEC SQL FETCH ABSOLUTE 5 FROM <游标名> INTO <变量表>
动态 SQL 语句
有时,在实际问题中,源程序往往还不能包括用户的所有操作,用户对数据库的操作需要在系统运行时才能提出来,这就要使用嵌入式 SQL 的动态技术才能实现。
- 动态 SQL 预备语句
EXEC SQL PREPARE <动态SQL语句名> FROM <共享变量或字符串>
- 动态 SQL 执行语句
EXEC SQL EXECUTE <动态SQL语句名>
存储过程
存储过程 是使用 SQL 语句和流程控制语句编写的模块,存储过程经编译和优化后存储在数据库服务器端的数据库中,使用时调用即可。
- 存储过程具有以下优点:
- 提高运行速度。运行之前,数据库会分析其语法及语义,给出优化执行方案;调用时,其执行 SQL 语句的大部分准备工作已经完成,所以执行速度很快。相比之下,交互执行的 SQL 语句是解释执行的,速度较慢。
- 增强了 SQL 的功能和灵活性。因为有流程控制语句,灵活性很高,能完成复杂的逻辑和运算。
- 可以降低网络的通信量。存储过程保存在服务器端,可想而知,传输一大堆 SQL 语句和只传输一个调用的存储过程名之间的带宽使用率是完全不同的。
- 减轻了程序编写的工作量。减轻的关键是存储过程可被不同程序重用。
- 间接实现安全控制功能。例如,不允许用户直接使用某些表和视图,但可以使用存储过程完成允许范围内的信息查询。
- 存储过程的声明
CREATE PROCEDURE <存储过程名> (<参数>)
<局部声明>
<函数体>; -- 局部声明 和 参数 是可选的。
-- 通常,每个参数应有一个 SQL 数据类型,还应有一个参数模式:IN(输入值)、OUT(输出值),INOUT(可输入可输出)
也可声明一个函数,但必须给出返回类型(函数的限制比较多,相对于存储过程函数比较鸡肋!):
CREATE FUNCTION <函数名> (<参数>)
RETURNS <>
<局部声明>
<函数体>;
SQL / PSM
SQL / PSM 是 SQL 标准的一部分,指定了如何编写持久存储模块,提供流程控制语句来表示存储过程的应用逻辑。
- 有三种基本结构:
- 顺序执行。
- 条件分支语句。
- 循环语句。
IF <条件> THEN <语句列表>
ELSEIF <条件> THEN <语句列表>
......
ELSEIF <条件> THEN <语句列表>
ELSE <语句列表>
END IF;
-- 标准的 WHILE 循环结构
WHILE <条件> DO
<语句列表>
END WHILE
-- 标准的 REPEAT 循环结构
REPEAT
<语句列表>
UNTIL <条件>
END REPEAT;
-- 基于游标的循环结构
FOR <循环名> AS <游标名> CURSOR FOR <查询> DO
<语句列表>
END FOR
SQL 语言 - 数据库系统原理的更多相关文章
- 数据库系统原理之SQL(三)
数据库系统原理之SQL(三) 1. SQL的组成 1. 数据查询 2. 数据定义 3. 数据操作 4. 数据控制 2. 数据定义语言 CREATE创建数据库或数据库对象 创建数据库 ~~~ CREAT ...
- 数据库系统学习(六)-SQL语言基本操作
第六讲 SQL语言概述 基本命名操作 关系代数是集合的思想 关系演算是逻辑的思想(数学公式) SQL-86,SQL-89,SQL-92,SQL-99,SQL-2003,2008...发展过程标准 SQ ...
- 数据库系统原理之SQL(四)
数据库系统原理之SQL(四) 1. 数据更新 插入数据 INSERT-VALUES语句 #插入多条数据 insert [into] table_name (column_name,...) value ...
- SQL SERVER 简介及应用 - 数据库系统原理
SQL SERVER 是一个分布式的关系型数据库管理系统(RDBMS),具有客户 - 服务器体系结构,一般发行的版本有企业版.标准版.个人版.开发版. SQL SERVER 提供的服务 MS SQL ...
- 哈工大数据库系统 实验:练习并熟练掌握交互式 SQL 语言
实验目的:基于给定的 OrderDB 数据库, 练习并熟练掌握交互式 SQL 语言实验环境:sql sever 2008 附:OrderDB 表结构及表间的关系 /* 1 查询职工工资按高低排序的前2 ...
- 数据库系统学习(十)-嵌入式SQL语言之动态SQL
第十讲 嵌入式SQL语言之动态SQL 静态SQL 区别变量和属性:高级语言向嵌入式SQL传递变量的方法 动态SQL 动态构造SQL语句是应用程序员必须掌握的重要手段 SQL语句的动态构造示例 根据界面 ...
- 数据库系统学习(九)-嵌入式SQL语言之基本技巧
第九讲 嵌入式SQL语言之基本技巧 901 什么是嵌入式SQL语言 交互式SQL语言的局限性 嵌入式SQL语言 交互式和嵌入式语言的对比 高级语言中使用嵌入式语言需要解决的问题 902 程序与数据库连 ...
- 数据库系统学习(八)-SQL语言与数据库完整性和安全性
第八讲 SQL语言与数据库完整性 重难点 数据库完整性的概念 关系数据库 防止和避免数据库中不合理数据的出现 输入错误,操作失误,程序处理错误等 完整性约束条件的一般形式 对O操作集合,当出现A情况时 ...
- 数据库系统学习(七)-SQL语言之复杂查询与视图
第七讲 SQL语言之复杂查询与视图 基本内容 子查询 IN与NOT IN谓词子查询 判断某一表达式的值是否在子查询的结构中 非相关子查询 相关子查询 theta some /theta all谓词子查 ...
随机推荐
- linux msql
安装mysql 1.使用rpm 安装mysql 或者使用yum安装 使用rpm 安装 下载 Centos 7 所需要的mysql包 tar -xf 解压整合包 根据依赖 安装 common>li ...
- 字节序相关问题简单总结,LSB与MSB
细细碎碎的知识点还真是不少啊,今天总结下通信中的数据字节序的问题. 先来认识名词: MSB:Most Significant Bit. “最高有效位” LSB:Least Significant ...
- docker 源码分析 三(基于1.8.2版本),NewDaemon启动
本文来分析一下New Daemon的启动过程:在daemon/daemon.go文件中: func NewDaemon(config *Config, registryService *registr ...
- No.2 CAS之SPNEGO+LDAP认证配置
1.概述 本文先配置了SPNEGO认证,就是如果用户操作系统如果登陆了公司的Windows域,用户浏览器访问应用服务即可免登录. 然后如果不在域里的员工,用LDAP认证方式,输账号密码登陆. 参考文档 ...
- 删除hao123这个恶心的毒瘤
最近做服务器,好好一个东西莫名其妙的被染上了这个狗皮膏药......然后我就用了各种手段删除,注册表.组策略等等都用上了,却没有丝毫办法.....最后发现的地方特别无语,居然在快捷方式的属性中加上了u ...
- Java的CLASSPATH,趁还没忘赶紧写点
咳咳,睡眠不足加上年龄增长,真的赶脚记忆力不行啦. 接触Java以来,对于环境配置就是按照网上的教程,一路复制粘贴,也没啥想法; 最近决定啃啃ThinkInJava,没看两章就看到这CLASSPATH ...
- 关于AE
1.下方时间轴左边上角时间,按住ctrl点击,可切换时间与帧数 2.新建comp,ctrl+n 3.特效控制面板,F3 4.时间轴左边图层各个属性快捷键:移动,p:旋转,r:缩放,s:轴心,a:不透明 ...
- iOS--时间类date详解
NSDate定义时间的类 NSDate是一个时间类,在编写程序时,我们很少遇到.今天我突然碰到,感觉很生疏. 给大家发个博客,让大家也都温习一下,哈哈! 兄弟用的时候突然发现竟然有一些bug,大家用时 ...
- HBase学习笔记-HBase性能研究(1)
使用Java API与HBase集群交互时,需要构建HTable对象,使用该对象提供的方法来进行插入/删除/查询等操作.要创建HTable对象,首先要创建一个带有HBase集群信息的配置对象Confi ...
- Lae程序员小漫画(二),仅供一乐
Lae软件开发,快乐程序员!