1.SQL概述

SQL的特点

综合统一

高度非过程化

面向集合的操作方式

以同一种语法结构提供多种使用方式

语言简洁,易学易用。

SQLALCHEMY定义model_Sage

SQL的基本概念

SQLALCHEMY定义model_Sage_02

2.数据定义

SQLALCHEMY定义model_数据库_03

早期数据库系统,所有数据库对象都属于一个数据库,也就是说只有一个命名空间。
现代的数据库系统,一个数据库管的实例中可以建立多个数据库,一个数据库中可以建立多个模式,一个模式下通常包括多个表、视图和索引等数据库对象。

模式

定义模式

定义模式实际上定义了一个命名空间,在这个空间中可以进一步定义该模式包含的数据库对象。例如基本表、视图、索引等。
基本模板:

CREATE SCHEMA <模式名> AUTHORIZATION <用户名>[<表定义子句>|<视图定义子句>|<授权定义子句>]

如果没有指定模式名,模式名隐含为用户名。

例、为用户ZHANG创建一个模式TEST,并且在其中定义一个表TAB1

CREATE SCHEMA TEST AUTHORIZATION ZHANG 
CREATE TABLE TAB1   ( COL1 SMALLINT, 
                                            COL2 INT,
                                            COL3 CHAR(20),
                                            COL4 NUMERIC(10,3),
                                            COL5 DECIMAL(5,2)
                                          );
删除模式

模板:

DROP SCHEMA <模式名> <CASCADE|RESTRICT>

CASCADE和RESTRICT必须两者选其一。CASCADE(级联),表示删除模式同时把模式中的所有数据库对象全部删除;RESTRICT(限制),表示只删除模式中没有数据库对象的模式。

模板:

CREATE TABLE <表名>
      (<列名> <数据类型>[ <列级完整性约束条件> ]
      [,<列名> <数据类型>[ <列级完整性约束条件>] ] 
   …
      [,<表级完整性约束条件> ] );
数据类型

SQLALCHEMY定义model_SQLALCHEMY定义model_04

修改基本表
ALTER TABLE <表名>
[ ADD[COLUMN] <新列名> <数据类型> [ 完整性约束 ] ]
[ ADD <表级完整性约束>]
[ DROP [ COLUMN ] <列名> [CASCADE| RESTRICT] ]
[ DROP CONSTRAINT<完整性约束名>[ RESTRICT | CASCADE ] ]
[ALTER COLUMN <列名><数据类型> ] ;
  • ADD子句用于增加新列、新的列级完整性约束条件和新的表级完整性约束条件
  • DROP COLUMN子句用于删除表中的列
  • 如果指定了CASCADE短语,则自动删除引用了该列的其他对象
  • 如果指定了RESTRICT短语,则如果该列被其他对象引用,关系数据库管理系统将拒绝删除该列
  • DROP CONSTRAINT子句用于删除指定的完整性约束条件
  • ALTER COLUMN子句用于修改原有的列定义,包括修改列名和数据类型
删除基本表
DROP TABLE <表名>[RESTRICT| CASCADE];
  • RESTRICT:删除是有限制的,欲删除的表不能被其他表的约束所引用(如check,foreign key等),不能有视图,不能有触发器。
  • CASCADE:删除时没有任何限制条件,删除的同时,相关的依赖对象一同删除。
  • 默认为RESTRICT

索引

当用户数据较大时,查询操作会比较耗时。建立索引可以加快查询速度。索引可以理解为字典中的目录,根据目录查找某个字与随便查快很多。虽然说建立索引可加快查询速度,但是它也有一定的缺点。它需要占用一定的存储空间,当基本表更新时,索引要进行相应的维护,这样会增加数据库的负担。

建立索引
CREATE [UNIQUE] [CLUSTER] INDEX <索引名> 
ON <表名>(<列名>[<次序>][,<列名>[<次序>] ]…);
  • <表名>:要建索引的基本表的名字
  • 索引:可以建立在该表的一列或多列上,各列名之间用逗号分隔
  • <次序>:指定索引值的排列次序,升序:ASC,降序:DESC。缺省值:ASC
  • UNIQUE:此索引的每一个索引值只对应唯一的数据记录
  • CLUSTER:表示要建立的索引是聚簇索引

例:为学生-课程数据库中的Student,Course,SC三个表建立索引。Student表按学号升序建唯一索引,Course表按课程号升序建唯一索引,SC表按学号升序和课程号降序建唯一索引

CREATE UNIQUE INDEX  Stusno ON Student(Sno);
   CREATE UNIQUE INDEX  Coucno ON Course(Cno);
   CREATE UNIQUE INDEX  SCno ON SC(Sno ASC,Cno DESC);
修改索引
ALTER INDEX <旧索引名> RENAME TO <新索引名>

例: 将SC表的SCno索引名改为SCSno

ALTER INDEX SCno RENAME TO SCSno;
删除索引
DROP INDEX <索引名>;

删除索引时,系统会从数据字典中删去有关该索引的
描述。

数据字典

数据字典是关系数据库管理系统内部的一组系统表,它记录了数据库中所有定义信息,包括关系模式定义、视图定义、索引定义、完整性约束定义、各类用户对数据库的操作权限、统计信息等。
关系数据库管理系统在执行SQL的数据定义语句时,实际上就是在更新数据字典表中的相应信息。

3.数据查询

SELECT [ALL|DISTINCT] <目标列表达式>[,<目标列表达式>] …
       FROM <表名或视图名>[,<表名或视图名> ]…|(SELECT 语句)      
                   [AS]<别名>
[ WHERE <条件表达式> ]
[ GROUP BY <列名1> [ HAVING <条件表达式> ] ]
[ ORDER BY <列名2> [ ASC|DESC ] ];
  • SELECT子句:指定要显示的属性列
  • FROM子句:指定查询对象(基本表或视图)
  • WHERE子句:指定查询条件
  • GROUP BY子句:对查询结果按指定列的值分组,该属性列值相等的元组为一个组。通常会在每组中作用聚集函数。
  • HAVING短语:只有满足指定条件的组才予以输出
  • ORDER BY子句:对查询结果表按指定列值的升序或降序排序

单表查询

select * from table_name;
选择表中的若干元组(条数据)
select <目标列> from table_name;

目标列不仅可以是表中的属性列,也可以是表达式
as给目标列去别名

消除重复

DISTINCT关键字可消除重复

select DISTINCIT * FROM TABLE_NAME;
查询满足条件的元组

SQLALCHEMY定义model_子查询_05


1.比较大小

select * from stu where age<20

2.确定范围
BETWEEN...AND...NOT BETWEEN...AND...可以用来查找指定范围的元组。

-- 查询20~30岁之间的学生
select * from stu where age between 20 and 30;

3.确定集合
谓词in可以用来查找属性值属于指定集合的元组。

-- 查询班级在101和102班的学生
select * from stu where class in (101,102);

4.字符匹配(模糊查询)
谓词like可以用来进行字符串的匹配。其一般语法如下:

[NOT] LIKE  ‘<匹配串>’  [ESCAPE ‘ <换码字符>’]

<匹配串>可以是一个完整的字符串,也可以含有通配符%和 _

  • % (百分号) 代表任意长度(长度可以为0)的字符串
    例如a%b表示以a开头,以b结尾的任意长度的字符串
  • _ (下横线) 代表任意单个字符。
    例如a_b表示以a开头,以b结尾的长度为3的任意字符串
-- 查询姓刘的学生
select * from stu where name like '刘%'

若需要匹配的字符中包含“%“或者“_”,则需要转码
例如:

-- 查询字符中包含%的字符信息
select * from str where name like '%\%%' ESCAPE '\'

“\%”表示引号中的%不是一个通配符
ESCAPE ''对通配符进行转义

5.涉及空值的查询
空值的判断是:IS NULL或者 IS NOT NULL

-- 查询学生表中地址为空的学生
select * from stu where address IS NULL;

6.多重条件查询
逻辑运算符ANDOR 可以用来连接多个查询条件。

order by

ORDER BY子句对查询可以按一个或多个属性列的升序(ASC)或降序(DESC)排列,默认为升序

-- 查询学生表的学生按学号降序排列
select * from stu order by id desc;
聚集函数

为了进一步方便用户,增强检索功能,SQL提供了许多聚集函数,主要如下:

SQLALCHEMY定义model_Sage_06

-- 查询学生总人数
select count(*) from stu
group by

GROUP BY将查询结果按某一列或多列的值分组,值相等的为一组。

-- 查询各个课程号及选课的人数
selec Cno,count(Sno) from SC GROUP BY Cno;

结果分组后也可以用having集合聚集函数对结果进行过滤。having与where的区别是它们作用的对象不同。where作用于基本表或视图,having作用于组。

-- 查询平均成绩大于90分的学生学号和平均成绩
select Sno,AVG(grade) from SC GROUP BY Sno HAVING AVG(grade)>90

连接查询

若一个表查询同时涉及两个以上的表,则称之为连接查询。连接查询是关系数据库中最主要的查询,包括等值连接查询、自然连接查询、非等值连接查询、自身连接查询、外连接查询和复合条件查询。

等值与非等值连接

where称之为连接条件或连接谓词。
当连接运算符为=时,称为等值连接。使用其他运算符称为非等值连接。
连接谓词中的列名称为连接字段。连接条件中的各连接字段必须是可比的,但名字不必相同。

SELECT  Student.*, SC.*
		         FROM     Student, SC
		         WHERE  Student.Sno = SC.Sno;

若在等值连接中把重复的属性列去掉则称为自然连接。

自身连接

自身连接即一个表与其自己进行连接。

select  t1.* from  table t1 ,table t2 where t1.id1 = t2.id2
外连接

LEFT [OUTER] JOIN
外连接即以某一张表为主体再与其他的表进行连接,外连接有左外链接和右外连接(RIGHT [OUTER] JOIN)。

select * from table1 t1 left join table2 on t1.id1 = t2.id2;
多表连接

连接操作除了可以是两张表,还可以是多张表,多张表时称为多表连接。

嵌套查询

在SQL语言中,一个SELECT-FROM-WHERE语句称为一个查询块。将一个查询块嵌套在另一个查询块中的WHERE子句或HAVING短语的条件中的查询称为嵌套查询。

SELECT Sname	                           /*外层查询/父查询*/
     FROM Student
     WHERE Sno IN
                        ( SELECT Sno        /*内层查询/子查询*/
                          FROM SC
                          WHERE Cno= ' 2 ');

需要注意的是子查询不能使用order by

带有in谓词的子查询

在嵌套查询中子查询的结果往往是一个集合,所以谓词IN是嵌套查询中最经常使用的谓词。

-- 查询成绩大于90的学生信息
select * from stu where id in(
	select id from stu_score where socre>90
)

子查询的条件不依赖与父查询,这类子查询称为不想关子查询。
子查询的查询条件依赖于父查询,这类子查询称为相关子查询,整个查询语句称为相关嵌套查询。

带有ANY(SOME)或ALL谓词的子查询

子查询返回单值时可以使用比较运算符,但返回多值时要用ANY或ALL谓词修饰符。而使用ANY或ALL谓词时必须同时使用比较运算符。

> ANY	大于子查询结果中的某个值       
> ALL	大于子查询结果中的所有值
< ANY	小于子查询结果中的某个值    
< ALL	小于子查询结果中的所有值
>= ANY	大于等于子查询结果中的某个值    
>= ALL	大于等于子查询结果中的所有值
<= ANY	小于等于子查询结果中的某个值    
<= ALL	小于等于子查询结果中的所有值
= ANY	等于子查询结果中的某个值        
=ALL	等于子查询结果中的所有值(通常没有实际意义)
!=(或<>)ANY	不等于子查询结果中的某个值
!=(或<>)ALL	不等于子查询结果中的任何一个值

例1.查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄

SELECT Sname,Sage
    FROM    Student
    WHERE Sage < ANY (SELECT  Sage
                                         FROM    Student
                                         WHERE Sdept= ' CS ')
     AND Sdept <> ‘CS ' ;           /*父查询块中的条件 */

改版为聚集函数

SELECT Sname,Sage
     FROM   Student
     WHERE Sage < 
                             (SELECT MAX(Sage)
                               FROM Student
                               WHERE Sdept= 'CS ')
       AND Sdept <> ' CS ';

小于任意一个即小于最大的
例2:查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名及年龄。

-- 方法一:用ALL谓词
    SELECT Sname,Sage
    FROM Student
    WHERE Sage < ALL
                           (SELECT Sage
                            FROM Student
                            WHERE Sdept= ' CS ')
      AND Sdept <> ' CS ’;
-- 方法二:用聚集函数
        SELECT Sname,Sage
        FROM Student
        WHERE Sage < 
                               (SELECT MIN(Sage)
                                FROM Student
                                WHERE Sdept= ' CS ')
          AND Sdept <>' CS ';

事实上用聚集函数实现子查询通常比直接用ANY或ALL查询效率要高,ANY、ALL与聚集函数对应关系表示:

SQLALCHEMY定义model_数据库_07


=ANY等价于IN谓词,<ANY等价于<MAX,<>ALL等价于NOT IN。

带有EXISTS的谓词查询
  • 带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”
    - 若内层查询结果非空,则外层的WHERE子句返回真值
    - 若内层查询结果为空,则外层的WHERE子句返回假值
  • 由EXISTS引出的子查询,其目标列表达式通常都用 * ,因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义。

可以利用EXISTS来判断,x∈S,S⊆R,S=R,S∩R非空等是否成立。

例:查询所有选修了1号课程的学生姓名。

SELECT Sname
     FROM Student
     WHERE EXISTS
                   (SELECT *
                    FROM SC
                    WHERE Sno=Student.Sno AND Cno= ' 1 ');

集合查询

select 语句查询结果是元组的集合,所以多个select语句的结果可进行集合操作。集合操作主要包括并操作UNION、交操作(INTERSECT)、差操作(EXCEPT)

注意:参加集合操作的各查询结果的列数必须相同;对应数据类型也必须相同。

例:查询计算机科学系的学生及年龄不大于19岁的学生。

SELECT *
        FROM Student
        WHERE Sdept= 'CS'
        UNION
        SELECT *
        FROM Student
        WHERE Sage<=19;
  • UNION:将多个查询结果合并起来时,系统自动去掉重复元组
  • UNION ALL:将多个查询结果合并起来时,保留重复元组

基于派生表的查询

子查询不仅可以出现在WHERE子句中,还可以出现在FROM子句中,这时子查询生成的临时派生表称为主查询的查询对象。

通过FROM子句生成派生表时,AS关键字可以省略,但必须为派生关系指定一个别名。

4.数据更新

数据更新操作包括添加、修改、删除三种操作

插入数据(添加)

插入元组
INSERT
	INTO <表名> [(<属性列1>[,<属性列2 >…)]
	VALUES (<常量1> [,<常量2>]… );

如果没有指明任何属性列名,则新插入的元组必须在每个属性列上都有值

例:

-- 第一种
insert into table_name(filed1,files2,...filedn) values(value1,value2...valuen)
-- 第二种
insert into table_name values(..按顺序所有属性列的值..);
插入子查询结果
INSERT 
     INTO <表名>  [(<属性列1> [,<属性列2>…  )]
 	子查询;

修改数据

UPDATE  <表名>
    SET  <列名>=<表达式>[,<列名>=<表达式>]…
    [WHERE <条件>];

删除数据 DELETE

DELETE
       FROM     <表名>
       [WHERE <条件>];

5.空值处理

所谓空值就是“不知道”或“不存在”或“无意义”的值。SQL语言中允许某些元组的某些属性在一定情况下取空值,一般有以下几种情况:

  • 该属性应该有一个值,但目前不知道它的具体值
  • 该属性不应该有值
  • 由于某种原因不便于填写
空值的判断

IS NULLIS NOT NULL

约束条件
  • 有NOT NULL约束条件的不能取空值
  • 加了UNIQUE限制的属性不能取空值
  • 码属性不能取空值

6.视图

定义视图

建立视图
CREATE  VIEW 
             <视图名>  [(<列名>  [,<列名>]…)]
       AS  <子查询>
       [WITH  CHECK  OPTION];

WITH CHECK OPTION表示对对视图进行UPDATE,INSERT和DELETE操作时要保证更新、插入或删除的行满足视图定义中的谓词条件(即子查询中的条件表达式)

  • 关系数据库管理系统执行CREATE VIEW语句时只是把视图定义存入数据字典,并不执行其中的SELECT语句。
  • 在对视图查询时,按视图的定义从基本表中将数据查出。

例:建立信息系学生的视图。

CREATE VIEW IS_Student
        AS 
        SELECT Sno,Sname,Sage
        FROM     Student
        WHERE  Sdept= '信息系';
组成视图的属性列名:全部省略或全部指定
  • 全部省略:
    由子查询中SELECT目标列中的诸字段组成
  • 必须明确指定视图的所有列名的三种情况:
    某个目标列是聚集函数或列表达式
    多表连接时选出了几个同名列作为视图的字段
    需要在视图中为某个列启用新的更合适的名字

行内子集视图:视图从单个基本表导出,并且只是去掉了某些行和某些列,但保留了主码,则这类视图称为行内子集视图。
分组视图:带有聚集函数和GROUP BY 子句的查询来定义的视图。

删除视图
DROP VIEW <视图名> [CASCADE]

CASCADE级联删除视图,即把该视图和由它导出的视图一并删除。

查询视图

查询视图可以理解为表的查询,即把定义的视图当做一张表进行查询。

select * from view_name;

视图消解:从数据字典中取出视图的定义,把定义中的子查询和用户查询结合起来,转换成等价的对基本表的查询,然后在执行修正了的查询,这就是视图消解。

更新视图

更新视图是指通过视图来插入、删除、修改数据。
由于视图不是实际存储数据的表,因此对视图的更新最终要转换为对基本表的更新(视图消解)

update view_name set filed1=value1 where id = 1;

一般各个数据库系统只允许对行列子集视图进行更新。

视图的作用

  • 视图可以简化用户操作
  • 视图使用户能以多种角度看待同一数据
  • 视图对重构数据提供了一定的逻辑独立性。
  • 视图能够对机密数据提供安全保护
  • 适当利用视图可以更清晰的表达查询。