type
status
date
slug
summary
tags
category
icon
password

3.1 SQL语言概述

3.1.1 SQL语言概念

SQL( Structured Query Language,结构化查询语言 )是一种对关系数据库进行访问的数据操作语言

3.1.2 SQL标准发展历史

历史,了解即可
  • 20世纪70年代由IBM公司研制的SEQUEL语言演变出SQL语言
  • 1979年ORACLE公司首先推出商用SQL
  • 1986 美国国家标准局批准了SQL作为关系型数据库语言的ANSI标准。
  • 1987年国际标准化组织(ISO)将其采纳为国际标准SQL86。
  • ISO先后推出国际标准SQL-89、SQL-92、SQL:1999、SQL:2003、SQL:2006、SQL:2008、SQL:2011、 SQL:2016等

3.1.3 SQL应用情况

应用情况也只要了解就好了,只需要SQL语言是用来对关系数据库进行操作的就好了
主流的关系型数据库管理系统均支持SQL标准语言实现数据库操作
  • Oracle
  • Sybase
  • DB2
  • Microsoft SQL Server
  • MySql
其中一些厂商数据库管理系统对SQL语句进行了功能扩展,如SybaseASE、 Microsoft SQL Server将SQL操作语言扩展为Transaction-SQL语言;Oracle Database将SQL操作语言扩展为PL/SQL语言

3.1.4 SQL语言特点

  • 一体化
  • 使用方式灵活
  • 非过程化
  • 语言语句简单

3.1.5 SQL对关系数据库的操作原理

SQL主要功能如下:
  • 数据库对象创建、修改、删除(对数据库的操作)
  • 数据库表的数据插入、修改、删除、查询、统计(对关系表的操作)
  • 存储过程、触发器、函数等程序执行(对函数以及触发器的操作)
  • 数据库权限、角色、用户等管理 (权限管理)

3.1.6 SQL语言语句类型

  • 数据定义语言:数据定义语言(Data Definition Language,DDL)是SQL语言中用于创建、修改或删除数据库对象的语句(就是在操作数据库中对象的语言,如操作数据库,操作关系表,操作索引等)。下面是一些数据定义SQL的示例(示例不用背,只要知道哪些SQL语句是数据定义语言就好了):
    • CREATE DATABASE - 创建新数据库
    • DROP DATABASE – 删除数据库
    • ALTER DATABASE - 修改数据库属性
    • CREATE TABLE - 创建新表
    • ALTER TABLE – 修改数据库表结构
    • DROP TABLE - 删除表
    • CREATE INDEX - 创建索引
    • DROP INDEX - 删除索引
  • 数据操纵语言:数据操纵语言(Data Manipulation Language,DML)是SQL语言中用于增添、修改、删除数据的语句(就是在操作数据库中数据的语言)。下面是一些数据操纵语言的示例(同样不用背):
    • INSERT - 向数据库表中插入数据
    • UPDATE - 更新数据库表中的数据
    • DELETE - 从数据库表中删除数据
  • 数据查询语言:数据查询语言(Data Query Language,DQL)是SQL语言中用于对数据库进行数据查询的语句。(如SELECT)
  • 数据控制语言:数据控制语言(Data Control Language,DCL)是用于对数据库对象访问权进行控制的SQL语句(只要把这里的控制理解为访问权的控制即可)。下面是一些数据控制语言的示例(同样不用背):
    • GRANT – 授予用户对数据库对象的权限
    • DENY – 拒绝授予用户对数据库对象的权限
    • REVOKE – 撤消用户对数据库对象的权限
  • 事务处理语言:事务处理语言(Transaction Process Language,TPL)是SQL语言中用于数据库内部事务处理的语句(事务处理语言是用来处理事务的很合理吧)。下面是一些事务处理语言的示例(不用背):
    • BEGIN TRANSACTION – 开始事务
    • COMMIT – 提交事务
    • ROLLBACK – 回滚事务
  • 游标控制语言:游标控制语言(Cursor Control Language,CCL)是SQL语言中用于数据库游标操作的语句(游标控制语言是用来处理游标的很合理吧)。下面是一些游标控制语言的示例(不用背):
    • DECLARE CURSOR – 定义游标
    • FETCH INTO – 提交游标数据
    • CLOSE CURSOR– 关闭游标

3.1.7 SQL语言的数据类型

这个挺重要的,不然到时候建表的时候用户自定义完整性约束中的数据类型都写不清楚
  • SQL语言基本数据类型
    • 字符:CHAR(是固定长度字符串,长度不足保存空格)、VARCHAR(长度可变字符串)、TEXT
    • 整数:SMALLINT(16位有符号整数)、INTEGER(32位有符号整数)
    • 浮点数:NUMBER(n,d)、FLOAT(n,d)(都是表示数据位数为n,小数的位数为d。如果没有小数部分就自动补0,所以NUMBER(5,2)能表示的最大的数为999.99。另外需要注意FLOAT不一定支持FLOAT(n,d)这种写法
    • 日期:DATE(包含年月日)、DATETIME(包含年月日时分秒)
    • 货币:MONEY
  • 不同数据库支持的数据类型(数据库支持的类型应该是由DBMS决定的,因为数据库本身应该就是一个文件,并不能标识不同的数据类型,将数据库中的字节序转换为什么数据类型是由DBMS决定的)
    • 这里只需要特别关注一下PostgreSQL中的主要数据类型即可
    • PostgreSQL主要数据类型(这个可以去看cal的ppt能了解更多的数据类型)
      • notion image
        image-20240516112336325
        需要注意的是,在 PostgreSQL 中,DECIMAL和 NUMERIC是完全相同的,并且同样需要使用NUMERIC(5,2)这样的形式来表示数据长度5位,小数部分为两位
    • SQL Server主要数据类型
      • notion image
        image-20240516112716115
    • MySQL主要数据类型
      • notion image
        image-20240516112818325
到这里就可以开始按照类型来介绍不同类型的SQL语句了。这些SQL语句是重点,需要背下来

3.2 数据定义SQL语句

先复习一下数据定义SQL语句的作用——是对数据库中的对象进行操作的语言。所以在这里将会介绍如何创建删除修改一个数据库或者关系表

3.2.1 数据库创建SQL语句

  • 语句基本格式:
    • 如要创建一个名为CourseDB的数据库:
      需要注意的点是每一条SQL语句的末尾也是需要加上分号的
      使用的是CREATE关键字

3.2.2 数据库修改SQL语句

  • 语句基本格式:
    • 如要将CourseDB数据库的名称修改为CourseManageDB:
      (好像数据库的修改只有修改数据库名字)
      使用的是ALTER关键字

3.2.3 数据库删除SQL语句

  • 语句基本格式:
    • 如要删除CourseManageDB数据库:
      使用的是DROP关键字

3.2.4 数据库表创建SQL语句

从这里开始就要介绍有关关系表操作的SQL语句了。前面操作数据库的语句中使用的都是DATEBASE,这里自然就要将DATEBASE换为TABLE了
  • 语句基本格式
    • 这里提到了列完整性约束(实际上就是用户自定义完整性约束),这里稍微介绍一下一些SQL语句中的列完整性约束关键字
  • 列完整性约束关键字
    • PRIMARY KEY——主键
    • NOT NULL——非空值
    • NULL——空值
    • UNIQUE——值唯一
    • CHECK——有效性检查
    • DEFAULT——缺省值
  • 数据库表创建SQL语句实例
    • 对下表:
      notion image
      image-20240516203854429
      创建数据库表的SQL语句为:
      需要注意的是,在括号内部,每一行的结尾都需要加上逗号,除了最后一行。并且创建表SQL语句结束需要加上分号
      在这里并没有使用到所有的列完整性约束关键字,所以下面再额外介绍剩下的几个列完整性约束关键字的使用
  • 其它的列完整性约束应用
    • UNIQUE——值唯一
    • CHECK——有效性检查
    • DEFAULT——缺省值
    • 下面给出一个使用了上面三个关键字的SQL语句例子:
      可以发现实际上这三个关键字都是要在数据库表创建的每一行的末尾使用的。里面比较值得注意的就是这里CHECK关键字在前面说是有效性检查,正常使用的时候就是用来确定一个属性的值域
      还有就是这三个关键字的使用格式,因为比较少使用,所以这里需要特别记一下
  • 表约束定义主键(主要是定义复合主键)
    • 使用列约束关键词PRIMARY KEY定义表的主键列只能定义单列主键,若要定义由多个列构成的复合主键,则需要使用表约束方式来定义
    • 表约束定义主键语句基本格式
      • 从这里可以看出表约束定义主键实际上就是将主键列合起来并且为其取了一个别名(也就是约束名)
        如要创建下表的主键:
        notion image
        image-20240516204855141
        则使用的SQL语句为:
        这里就使用了复合主键,主键由CourseID和TeacherID两列构成,并为这个复合主键取了一个别名CoursePlan_PK。同样的,由于比较少使用复合主键,所以表约束定义主键也比较少见,所以这里也需要特别记一下表约束定义主键的格式
  • 使用表约束定义代理键
    • 先复习一下代理键是什么——首先代理键本身也是一个主键,只不过它是由数据库系统自动产生的(并且在写创建数据库表的SQL语句时并不会给代理键加上primary key关键字。而体现一个属性为代理键的关键就是这个属性的数据类型是自动编号,然后需要将代理键作为主键就一定要使用表约束来指定代理键为主键)。所以讲道理使用表约束定义代理键也就是使用表约束定义主键了
    • 使用表约束定义代理键语句格式:
      • 如要创建下表:
        notion image
        image-20240516205743701
        则编写的SQL语句为:
        需要注意的点这里再强调一次,就是代理键的数据类型一定是serial(自动生成),并且如果要将代理键作为主键使用的话,就一定要使用表约束
  • 使用表约束定义外键
    • 同样的首先先来复习一下外键是什么。如果一个属性在某张关系表中是主键,并且他在另一张表中也出现了,那么就可以将这张表中的该属性定义为外键来表示表之间的关系。此外,外键还涉及到了参照完整性约束,这里就不赘述了
    • 表约束定义外键语句格式:
      • 这里能看出跟上面表约束定义主键以及表约束定义代理键不一样的地方就是使用的关键字不一样。上面的表约束定义主键和代理键的CONSTRAINT中使用的就是PRIMARY Key,而在定义外键中使用的就是FOREIGN Key。并且在表约束定义外键中还需要定义这个外键是参考哪张表中的哪个属性。此外还可以增加字段ON DELETE CASCADE以表示当主键某个值被删除的时候对应的外键元组是否需要被连带删除
        如要创建下表:
        notion image
        image-20240516211033035
        则可以使用一个表约束定义代理键还有两个表约束定义外键来实现:
        同样的,这里也是在表创建SQL语句中的每一行都是需要加上逗号的,除了最后一行
  • 使用表约束的优点
    • 便于定义复合主键(因为使用primary key关键字只能定义单列主键。疑问只包含一列的键叫什么来着?)
    • 命名主键约束(可以给主键取一个别名,如上面的CoursePlan_PK)
    • 便于定义代理键(也就是表约束定义代理键)
    • 声明外键(也就是表约束定义外键)

3.2.5 数据库表修改SQL语句

  • 语句基本格式:
    • 这里提到了修改方式(就说明表结构修改不仅仅是像数据库一样只有修改名称),下面就介绍一下修改方式
  • 主要修改方式(就是上面的基本格式中提到的修改方式)
    • ADD修改方式,用于增加新列或列完整性约束
      • 后面部分实际上就是对应了数据库表创建中的一行
        这里还有一个小坑,如果需要添加的列有非空完整性约束的话,那么在表中已经有数据的情况下他就不能直接添加。因为如果已经添加了的话就会导致原有数据中的这一列不满足非空的完整性约束。所以操作应该是先创建一个可以为空的属性列,将已有数据的所有该属性的值都填写了之后再给这一列添加列完整性约束。所以这里写的是可以添加<新列名称><数据类型>或者[完整性约束](这个完整性约束就是指表约束)。并且根据copilot的提示,这里表约束是可以使用除了NOT NULL的所有关键字的(如何添加一个非空约束下面会介绍)。如创建一个唯一值表约束:
    • DROP修改方式,用于删除指定列或列的完整性约束条件
      • 需要注意的就是这里需要提供删除的对象是什么(是列还是约束)。并且这里将表约束称为完整性约束好像没有什么问题,因为表约束中定义的就是主键、代理键、外键,就对应了实体完整性约束以及参照完整性约束
    • RENAME修改方式,用于修改表名称、列名称
      • 这里跟修改数据库的名称是一样的,都是使用rename to关键字。如果RENAME TO放在一起就是表示要修改数据库或数据库表的名称;如果是分开的话就要使用格式:rename 原列名 to 新列名
    • ALTER修改方式,用于修改列的数据类型
      • 需要通过COLUMN指定需要修改的列,并通过TYPE来指定新的数据类型
        根据copilot的提示,如果要给一个列加上一个非空约束,需要使用下面的SQL语句:
        需要注意的是这里ALTER搭配了SET关键字使用
      需要注意的是这里的DROP和ALTER都是加上COLUMN关键字的

3.2.6 数据库表删除SQL语句

  • 语句基本格式
    • 如要删除关系表Register:

3.2.7 索引简介

  • 索引的概念:索引(Index)是一种按照关系表中指定列的取值顺序组织元组数据存储的数据结构,使用它可以加快表中数据的查询访问。(牺牲空间赢得时间)。为了便于理解索引的原理,下面摆上一张图:
    • notion image
      image-20240516213755779
      看样子索引就好像是一个线段树。因为对线段树的查找比较快,所以创建索引能够加快查找速度;但是需要存储分支节点,所以会占用空间
  • 索引的作用:支持对数据库表中数据快速查找,其机理类似图书目录可以快速定位章节内容(就跟索引的概念中说道的是一样的)
  • 索引的优点(说白了就是加快了处理速度):
    • 提高数据检索速度
    • 快速连接关联表
    • 减少分组和排序时间
  • 索引的开销(就是牺牲空间还有开销的问题)
    • 创建和维护索引都需要较大开销
    • 索引会占用额外存储空间
    • 数据操纵因维护索引带来系统性能开销

3.2.8 索引创建SQL语句

  • 语句基本格式
    • 需要注意的是索引是一个列(属性)创建的,所以在这里需要指定表名和列名。创建索引也比较少用一般只会在主键上创建索引,所以这里也需要记一下创建索引的格式,特别是关键字INDEX。。。ON。。。
      如在学生信息表Student中,要为出生日期Birthday列创建索引:

3.2.9 索引修改SQL语句

  • 语句基本格式
    • 如要将Birthday_Idx更名为Bday_Idx:

3.2.10 索引删除SQl语句

  • 语句基本格式
    • 删除使用的都是DROP关键字
      如要删除Bday_Idx索引:

3.3 数据操纵SQL语句

这里需要阐述一下wyd和cal的ppt中的不同点
  • 在w的ppt中,将SQL语句分为6类,其中有两个类型:数据操纵语言(包括增删改)和数据查询语言(包括查)
  • 但是在c的ppt中,只将SQL语言分为五类,认为增删改查都属于数据操纵语言,所以就没有数据查询语言了
关于这个不同,copilot给出的答案是:
notion image
image-20240516150312804
少了一个游标控制语言。但是能看出copilot认为查询还是要单独分出来的,所以还是认为wyd的是对的(选多的应该不会有什么问题),所以这里在数据操纵语言这一节中只介绍增删改,并不介绍查询。
好好好,cal只是在前面分类的时候分了五类,但是后面讲的时候还是将数据查询语言和数据操纵语言分开了
下面开始正式进入3.3
从上面的分类中可以知道,数据操纵语言主要有三个操作,就是增删改,所以这里就介绍增删改三个SQL语句

3.3.1 数据插入SQL语句

  • 语句基本格式
    • 需要注意的是这里有一个INTO,并且VALUE后是一个圆括号,还有就是INSERT语句可以对视图使用。并且可以执行一组INSERT语句来实现一组数据的插入(实际上就是上面这个INSERT语句写了很多遍)
      如要在Student表中插入一条数据(“2017220101105” , “柳因” , “女” , “1999-04-23” , “软件工程” , “liuyin@163.com”):

3.3.2 数据更新SQL语句

  • 语句基本格式
    • 需要注意的是这里有一个SET关键字要和UPDATE搭配使用。此外一般进行更新的列是需要有一些条件约束的,所以会使用到where子句。并且在数据定义语言中更新数据一般都是使用ALTER,这里是使用UPDATE SET,需要注意区分
      如需要将学生“赵东”的邮箱设置为zhaodong@163.com:

3.3.4 数据删除SQL语句

  • 语句基本格式
    • 需要注意的是,这里也是有一个FROM关键字搭配DELETE关键词一起使用的,并且这里需要删除的元组(删除一定是一下删除整个元组)一般也是需要有一些条件约束的,所以也会使用到where子句。还有就是在数据定义语言中的删除一般都是使用DROP关键字,这里是使用DELETE FROM关键字,需要注意区分
      如要删除STUDENT表中“张亮”的数据:
      需要注意的是,在where语句中判等也是使用单个等号

3.4 数据查询SQL语句

3.4.1 数据查询SQL语句格式

这位更是重量级,一定要背下来
需要注意的点就是这里的ALL和DISTINCT的使用(默认情况下是ALL,也就是不去重)、INTO关键字,还有就是需要注意GROUP BY是在ORDER BY前面的(这里实际上就涉及到了一个SQL语句的执行顺序,应该是自上而下执行的,疑问,是自上而下执行的吗?一般都是先将数据分组了之后再将分组进行排序,因为如果先排序再进行分组的话刚刚排的序就会被打乱。所以GROUP BY在ORDER BY前面)
这里是一个SELECT语句的整体格式,相当于是母式了。感觉这个背下来下面的都是按需来搞就好了

3.4.2 从单个表读取指定列

也就是进行列运算
  • 语句基本格式(读取指定列的时候就是在目标列上做文章)
    • 需要注意的是这里的目标列在需要查询所有的列的时候是可以使用通配符*来代替的
      如要从Student表查询学生的学号、姓名、专业列:
      如果需要将查询出来的结果进行去重,可以使用DISTINCT关键字(这里以查询Student中的Major属性为例):
      从这里就可以发现SELECT语句实际上并不是一个投影操作(因为投影操作是会去重的),如果想要将SELECT转换为一个投影操作的话就需要手动去重,也就是加上DISTINCT关键字

3.4.3 从单个表读取指定行

也就是进行行运算
  • 语句基本格式(读取指定行的时候就是要在查询条件上做文章)
    • 如要在Student表中查询所有男生的数据:

3.4.4 从单个表中读取指定行和列

也就是进行行列运算,就是把上面两个结合起来了
  • 语句基本格式(就是在目标列以及where子句上做文章)
    • 如要从Student表中查询性别为“男”的学生学号、学生姓名、专业数据。

3.4.5 WHERE子句

前面也一直在用,实际上就是一个查询条件
  • WHERE子句的使用方式:这里就没有介绍一般的使用方式了(比如属性相等等)
    • 使用BETWEEN..AND关键词来限定列值范围,还可以使用关键词LIKE与通配符来限定查询条件。(疑问between and有没有包括区间端点?我猜是有包括的)
    • 使用通配符来限定字符串数据范围。下划线(_)通配符用于代表一个未指定的字符百分号(%)通配符用于代表一个或多个未指定的字符(所以这里的百分号就相当于是正则表达式中的+号)
      • 下面是一个使用LIKE关键字以及通配符的例子(LIKE关键字就表示我要查询这样的元组):
    • 在WHERE子句中还可以使用逻辑运算符(在SQL语句中是关键字)AND、OR、NOT以及IN或NOT IN关键词(这个是用来限定取值范围的)
      • 如要从STUDENT表中查询性别为“男”,并且专业为“软件工程”的学生数据:
        还有一个使用IN关键字的例子(从STUDENT表中查询“计算机应用”专业的学生):
        讲道理如果像这样取值范围中只有一个取值的话完全可以直接使用等号

3.4.6 对结果集进行排序

  • 单列排序:
    • 在SELECT查询语句返回的结果集中,行的顺序是任意的。如果需要结果集排序,可以在SELECT语句中加入ORDER BY关键字。
      如要在STUDENT表中按学生出生日期降序输出学生数据:
      需要注意的是在默认情况下使用的是升序排序。在ORDER BY子句的最后可以使用关键词ASCDESC指定排序是升序还是降序
  • 多列排序:
    • 如果要按照多列进行排序,可以(若要将STUDENT表查询数据,首先按出生日期降序排列,然后按姓名升序排列):
      这个时候会优先Birthday降序排序,然后StudentName升序排序

3.4.7 SQL内置函数

这里一些内置函数只需要稍微了解一下就好了,只需要记住一些常用的就好了,剩下的混个脸熟就行了
内置函数是用于对SELECT结果集进行处理
典型SQL内置函数类型如下:
  • 聚合函数(如COUNT等)
  • 算术函数
  • 字符串函数
  • 日期时间函数
  • 数据类型转换函数

3.4.8 SQL聚合函数

在SQL的内置函数中,比较常用的就是SQL的聚合函数,常用来统计
  • 聚合函数概念:聚合函数是一些对关系表中数值属性列进行计算并返回一个结果数值的函数(就是将很多东西聚合成一个数据)
    • 常见的聚合函数有:
      notion image
      image-20240517090950618
      感觉聚合函数使用的比较多,这就全记下来吧
      这里有一个使用COUNT函数的例子(以要统计Student表中的学生人数为例):
      COUNT关键字记录的是指定列非空的行数,这个在进行外连接的时候很重要。另外,需要注意的是这里的AS关键字就相当于是给COUNT出来的结果取了一个别名。执行结果如下:
      notion image
      image-20240517091230615
      此外还可以在SELECT中使用多个聚合函数(找出STUDENT表中年龄最大和年龄最小的学生出生日期):
      多个聚合函数的使用之间就使用逗号隔开,就好像之前选取多个列一样
      这里就可以稍微讨论一下SQL语句的执行顺序了。因为聚合函数都是对结果集进行的操作,所以不难发现,实际上先是执行SELECT后的部分(比如FROM什么的),最后再执行SELECT语句从经过其他子句处理的结果视图中选取对应的属性列或者调用聚合函数

3.4.9 SQL分组统计

SQL语句中的分组统计通常是通过Group By子语句和SQL内置函数中的聚合函数实现的(这个时候聚合函数就是对每个分组进行聚合了。或者理解为GROUP BY的结果集是一堆表格,COUNT函数需要作用在每一张表格上。还记得Group By子语句要放在SELECT语句的哪里吗?是放在WHERE子句后,在ORDER BY子句前)
  • 分组统计SQL语句基本格式:
    • 需要注意的是在GROUP BY的基础上还能再使用一次Having子句对GROUP BY的结果进行条件筛选
      如需要分专业统计Student表中的学生人数:
      需要注意的是这里的COUNT是对结果集进行的聚合,需要理解SQL语句的执行顺序。以上面的SQL语句为例,首先先执行FROM,经过FROM后结果集为Student表,然后执行GROUP BY,执行结束后结果集应该为两张表(是根据Major)进行分组的。然后执行SELECT行。首先先是将两张表的Major取出作为专业(这个时候一张表中的所有数据的Major都是一样的,所以一张表只取出一个Major),然后对每个组进行在StudentID上的统计(也就是计算每个分组的学生人数)。由于最终选取出的视图就应该只有两行两列(专业和学生人数)。另外这里的COUNT(StudentID)可以替换为COUNT(*),因为COUNT函数是不考虑去重的
      或许到这里就想知道如何统计专业的数量(因为像上面一样分组了再使用COUNT函数就是统计各个分组的结果了):
      只需要加上一个DISTINCT关键字即可。同样来理一下执行顺序。首先执行FROM,结果集为Student,然后执行DISTINCT(因为括号的存在),使得Student表被投影到Major属性上(因为是投影,所以要去重),结果集为若干行一列(就是Major列),然后在Major上统计结果集中的行数,就计算出了专业的数量
      下面再给出一个比较复杂的例子(若要分专业统计STUDENT表中男生人数,但限定只显示人数大于2的人数):
      同样的这里SQL 语句的执行顺序也是先按顺序执行SELECT后的语句,然后再执行SELECT行。这里最重要的应该是怎么写出来这个SQL语句。首先要先明白条件的先后顺序。首先是要分专业统计,然后还要求是男生,那么就一定要先使用WHERE语句满足男生条件才能进行分组(因为WHERE子句是在分组子句之前的。这与现实是不一样的,在现实中可以先选出男生再统计专业,也可以先选出专业再统计男生),分组之后再使用HAVING子句满足数量大于2的条件即可
  • Group by与having理解
    • group by 有一个原则,就是 select 后面的所有列中,没有使用聚合函数的列,必须出现在 group by 后面或者包含在having 后的聚合函数里(可以理解为GROUP BY子句是将结果集投影到给定的属性列上,其他的属性只对聚合函数可见)。疑问这个HAVING怎么理解?并且只有使用了GROUP BY子句之后,列的名称(这个时候经过GROUP BY后列就变成了聚合列了)才允许和内置函数一起混合使用(是因为如果没有使用GROUP BY的话聚合函数的结果行数就不能和列行数对应了)
      • 下面有一个混合使用的反例:
        这里就是因为MaxHours列不是一个聚合列,所以查询出来的结果会使得聚合函数结果行数与该列的行数不对应。如果在SELECT子句后面只使用了SUM(MaxHours),那么就是一个正确的查询
    • where 子句的作用是在对查询结果进行分组前将不符合where条件的行去掉,即在分组之前过滤数据(条件中不能包含聚合函数)。
      • 下面是一个反例:
        这个查询语句不规范是因为在WHERE子句中使用了聚合函数。但是像上面的这种情况应该是会经常出现的。下面给出一种解决方法(使用子查询):
        这样就避免了在WHERE子句中使用聚合函数
    • having 子句的作用是筛选满足条件的组(也就是限制的是组,而不是元组),即在分组之后过滤数据(条件中经常包含聚合函数)。
    • 给上面做一个总结,实际上只要将GROUP BY子句当成投影操作,其他属性列仅对聚合函数可见(还有行信息。甚至不对紧跟在他后面执行的HAVING子句可见),聚合函数只能和聚合列(聚合列就是CROUP BY后指定的属性列)一同展示。并且聚合函数只能使用在SELECT和HAVING中
在ppt的末尾有一句话:having 子句中的每一个元素也必须出现在select列表中,不太明白这句话是什么意思。疑问

3.4.10 子查询实现多表关联查询

  • 子查询SQL语句基本格式(可以通过子查询解决WHERE中不能使用聚合函数的问题)
    • 如需要检索出“计算机学院”的教师名单:
      可以看出子查询在WHERE子句中通常是作为布尔表达式的一个部分

3.4.11 使用连接关联实现多表关联查询

  • 连接关联SQL语句基本格式
    • 从这里也可以看出,FROM语句后如果提供了多表,那么FROM语句的运算结果就是一个广义笛卡尔积,然后WHERE语句在这个笛卡尔积结果上实现选择(跟连接操作的逻辑是一样的)
      如在选课管理系统数据库中,希望获得各个学院的教师信息列表,包括学院名称、教师编号、教师姓名、教师性别、职称等信息,并按学院名称、教师编号分别排序输出:
      这里就在WHERE子句中使用了一个连接关联条件A.CollegeID=B.CollegeID

3.4.12 JOIN …ON关键字实现多表查询

这个关键字的使用跟上面使用连接关联进行的操作是一样的,只不过是把连接关联条件写在ON关键字后了,这样就可以使得WHERE子句能更专心处理一般的查询
  • JOIN…ON语句格式
    • 如在选课管理系统数据库中,希望获得各个学院的教师信息,包括学院名称、教师编号、教师姓名、教师性别、职称等信息并按学院名称、教师编号分别排序输出(实际上跟上面使用连接关联是一样的):
      需要注意的就是在FROM语句中是可以给表名称其别名的。另外,应该是子查询的功能更强大一点,因为子查询可以引用主查询中的表名,并且可以使用聚合函数。但是在进行关联查询或者使用JOIN关键字的时候就没办法使用聚合函数了(因为聚合函数只能在SELECT和HAVING中使用)

3.4.13 外部连接

之前多表连接方式在SELECT查询语句称为内部连接。 在一些特殊情况下,如关联表中一些行的主键与外键不匹配,查询结果集就会丢失部分数据。所以说默认情况下的连接就是内部连接(内部连接就是将两张表按照连接条件连接在一起并且行数取的是两张表中行数小的,所以会出现数据丢失的情况)
  • LEFT JOIN: 左外连接,即使没有与右表关联列值匹配,也从左表返回所有的行(行数取的是左表的行数)。
  • RIGHT JOIN: 右外连接,即使没有与左表关联列值匹配,也从右表返回所有的行(行数取的是右表的行数)。
  • FULL JOIN: 全外连接,同时进行左连接和右连接,就返回所有行(这个就与内连接完全相反,行数取的是两张表中行数大的)。
如果要使用这些连接就只需要将上面使用JOIN关键字连接替换为对应的关键字即可(如LEFT JOIN等)。此外需要注意的是,如果使用外连接的话一定要保证完整性约束(也就是没有数据的一侧不能有用户自定义的非空完整性约束)

3.5 数据控制SQL语句

  • 数据控制SQL语句概念:数据控制SQL语句是一种可对用户数据访问权进行控制的操作语句,它可以控制特定用户或角色数据表、视图、存储过程、触发器等数据库对象访问权限(想想之前在概述中记的,控制语句控制的是访问权限)。

3.5.1 GRANT权限授予语句

  • 基本语句格式:
    • 需要注意的是这里的权限列表实际上就是用户能使用的关键字,如SELECT、INSERT等。还有就是这个SQL语句也不常使用,需要背一下,尤其是这个ON和TO两个虚词关键字
      如需要将课程注册表REGISTER的数据插入、数据修改、数据删除、数据查询访问权限赋予学生角色RoleS:

3.5.2 REVOKE权限收回语句

  • 基本语句格式:
    • 这里的权限列表跟GRANT的权限列表是一样的,但是要注意关键字不再是TO了,而是FROM(这也挺符合英文的语法的)
      如要收回学生角色RoleS在课程注册表REGISTER的数据删除访问权限:

3.5.3 DENY权限拒绝语句

  • 基本语句格式:
    • 这里使用的关键字也是TO。需要注意的是权限拒绝语句一般都是在用户发起了一个权限请求的时候使用的。而权限收回是已经将权限赋予用户了,然后才需要收回
      如在选课管理系统数据库中,需要拒绝教师角色RoleT对教师表TEACHER的数据删除访问权限:

3.6 视图SQL语句

讲道理不知道SQL视图语句是属于SQL六大分类中的哪一个,感觉是定义?(毕竟视图也是一个数据库对象)
  • 视图的基本概念:视图是一种通过基础表或其它视图构建的虚拟表。它本身没有自己的数据,而是使用了存储在基础表中的数据(正如之前理解的,查询的结果就是一个视图)。如下图:
    • notion image
      image-20240517115329163
      讲道理这个图也挺抽象的

3.6.1 视图创建SQL语句

  • 语句基本格式
    • 我更加确定这个是属于数据定义语言了。这里就是把之前的DATABASE、TABLE或者INDEX的位置替换为了VIEW。需要注意的点就是最后是使用AS关键字跟上一个查询语句来创建视图的(印证了之前的想法,查询的结果就是一张视图,并且视图没有自己的数据——更正,查询结果并不是一个视图,而是一个游标。视图是需要创建的)。另外,当视图在数据库中创建后,用户可以像访问关系表一样去操作访问视图
      如要在选课管理系统数据库中建立一个查看基础课数据的视图BasicCourseView:
      疑问,上面语句基本格式中的列名是什么

3.6.2 视图删除SQL语句

  • 语句基本格式
    • 如需要删除名称为BasicCourseView的视图对象:

3.6.2 SQL视图应用

感觉这一节没啥用用,只需要知道视图是通过查询语句构建的,所以可以通过视图创建语句过滤掉一些无关的数据。这么来看视图创建时提供的SQL语句就好像是一个子查询一样,然后对视图进行的查询就是主查询
但是这几个点还是背一下,感觉有可能会出简答题
  • 使用视图简化复杂SQL查询操作:数据库开发人员可以将复杂的SQL查询语句封装在视图内(就是将复杂的SQL放在视图创建时提供的查询语句的位置),外部程序只需要使用简单的视图访问方式,便可获取所需要的数据。
  • 使用视图提高数据访问安全性:通过视图可以将数据表中敏感数据隐藏起来,外部用户无法得知数据表的完整数据(这是因为视图创建时提供的子查询),降低数据库被攻击的风险。此外,还可以保护用户隐私数据
  • 提供一定程度的数据逻辑独立性:当数据表结构发生改变,只要视图结构不变,应用程序可以不作修改
  • 集中展示用户所感兴趣的特定数据:通过视图,可以将部分用户不关心的数据进行过滤,仅仅提供他们所感兴趣的数据
Paper2PX4
Loading...
Noah
Noah
永远年轻,永远热泪盈眶
公告
❗❗复习笔记问题❗❗
由于兼容性问题
导入md文件可能导致了一些格式错误
🌹如发现格式错误,请联系我~🌹
🌹如博客内容有误也欢迎指出~🌹