数据库的创建
表的创建
命名规则
只能以字母开头,不能以数字或者下划线开头。
数据类型
约束的设置
NOT NULL 和primary KEY
表的删除与更新
表的删除(drop)
表定义的更新
表的修改
select 语句基础
列的查询
查询出表中所有的列
为列设定别名
别名可以使用中文,但是需要双引号括起来
常数的查询
删除重复行
Distinct可以在多列之间使用。
会将重复的数据合并为一条。
但是distinct关键字只能用子啊第一个列名之前。
根据where语句来选择记录
注释的写法
算数运算符和比较运算符
算数运算符
需要注意NULL值!
所有包含NULL的计算,结果都是NULL。如何使NULL作为0参与运算呢?之后会说明
From 子句真的有必要吗?
比较运算符
可以使用比较运算符对计算结果进行比较
对字符串使用不等号时的注意事项
在对字符串类型的数据进行大小比较时,使用的是和数字比较不同的规则。典型的规则就是按照字典进行比较。
不能对NULL使用比较运算符
关于比较运算符,还有一点比价哦重要,那就是作为查询条件的列中含有NULL值的情况。
当检索价格不为50元的食品时,如果某一食品的价格为NULL。则此时不能检索出该食品。
一下情况也不能使用。
不可以使用=null(=也是比较运算符)
如果想判断是不是null,可以使用is null ,或者 is not null
逻辑运算符
NOT 运算符
不大于1000元可以这样写
where sale_price <1000
或者where not sale_price>=1000
AND,OR运算符
and的运算优先级要高于or,如果逻辑过于复杂可以使用括号。
逻辑运算符和真值
and, or,not都是逻辑运算符。以上的比较运算符,会将结果以真假值的形式返回,true or false .
含有NULL的真值
使用逻辑运算符时也需要特别对待NULL。
当进行以上操作时,bananan是true还是false呢?
其实是第三种值不确定值(UNKNOWN).
其实完整的表应该是这样的
第三章 聚合与排序
3-1对表进行聚合查询
计算NULL之外的数据的行数
如果想计算某列补位NULL的行数的话,可以用·count(column)
SUM 与AVG中带有NULL的行时
会先出去带有NULL的行,在进行计算
计算最大值跟最小值
MAX 与 MIN
使用该函数可对日期进行计算
max 与min函数可以适用于任何类型的列。
使用聚合函数删除重复值(DISTINCT)
可以使用
select count(distinct type)
from product;
注意distinct 必须要写在括号中
如果写在括号外
select distinct count( type)
from product;
他的结果是无效的,相当于
select count( type)
from product;
3-2对表进行分组
group by
在group by 中指定的列称为聚合键或者分组列
此外group by子句有严格的要求,一定要写在from子句之后(如果有where 则写在where 之后)
聚合键中包含NULL的情况
当聚合键中包含NULL值时,会将NULL作为一组特定的数据
常见错误
-
在select 子句中书写了多余的列
在使用count这种聚合函数时,select子句中的元素有严格的限制。只用聚合函数时,select子句只能存在以下三种元素。
- 常数
- 聚合函数
- group by子句中制定的列
-
在group by子句中写了列的别名
在select子句中可以使用as 来指定别名,但是在group by子句中是不能使用别名的。
例如:
select product_type as pt,count(*)
from Product
group by pt;
但是为什么不能使用别名呢?
因为执行顺序是这样的
FROM -> WHERE -> GROUP BY -> SELECT
-
GROUP BY子句的结果能排序吗?
答案是不能。需要借助其他的子句。
-
在WHERE中使用聚合函数。
是有在select 和HAVING子句中才能使用聚合函数。
可能有的人发现,distinct 和GROUP BY 都能实现相同的去重结果。(在MongoDB中就可以使用group by来进行去重)
3-3为局和结果指定条件
HAVING
HAVING 子句的用法
此时就可以解决之前的问题(where中不能使用聚合函数)
HAVING 子句用于过滤分组
HAVING 子句构成的元素
- 常数
- 聚合函数
- GROUP BY 子句中指定的列名
相对于HAVING子句,更适合写在WHERE子句中的条件
有些条件既可以写在where子句中,也可以写在HAVING中,比如
两种结果相同,但是第二种的效率会更高一些。(因为索引的存在,以及where可以过滤一些不必要参加运算的行)
where 用来指定行的条件
HAVING 用来指定组的条件
3-4对查询结果进行排序
ORDER BY
不管什么情况,order by都必须在select 语句的末尾
指定升序和降序
- 降序:
DESC
- 升序:
ASC
order by 默认使用升序排列。
指定多个排序键
先参考左边的排序键,依次参考右边的。
NULL 的顺序
排序键中包含NULL时,会在开头或者末尾汇总。
在排序键中使用显示用的别名
在排序键中可以使用显示用的别名(select 子句中的别名)
因为执行顺序为
order by子句中可以使用的列
ORDER BY子局中也可以使用存在于表中,但并不存在SELECT 子句中的列。
此外还可以使用聚合函数
不要使用列编号
在ORDER BY 子句中还可以使用SELECT 子句中出现的列所对应的的编号。
但是并不推荐使用这种写法
- 代码阅读起来比较难。
第4章 数据更新
数据的插入(INSERT语句的使用方法)
什么是Insert
insert 基本语法
一般情况下,一条insert语句,只能插入一条数据。
但是insert支持多行插入。
列清单的省略
对表进行全列Insert 时,可以省略表名后的列清单。此时VALUES 子句的值会默认按照从左到右的顺序赋给每一列。
插入NULL
Inset语句想插入NULL值时,对应字段一定不能设置NOT NULL 约束。
插入默认值
我们还可以向表中插入默认值(初始值)。可以在创建表的语句中,设置DEFAULT约束来是定默认值。
如果创建表的同时设定了默认值,在Insert 语句中就有显式,和隐式两种方式赋值。
通过显式方式赋值插入默认值
在VALUES 子句中指定DEFAULT关键字
通过隐式方式赋值插入默认值
插入默认值是也可以不使用DEFAULT关键字,只要在清单和VALUES 中省略默认值就可以了。
还有一点需要说明,如果省略了没有默认值的列,该列的值就会被设定为NULL。如果省略的是设置了NOT NULL的列,并且没有默认值,那么INSERT 语句就会出错。
从其他表中复制数据
使用该insert 语句时,也可以使用where 子句或者GROUP by 子句等。但是使用ORDER BY 子句不会产生任何效果。
插入数据时,如果有中文可能导致插入失败,因此需要设置相应字段的编码(改为utf-8)
4-2 数据的删除(DELETE )
DROP TABLE 和DELETE 语句
1. DROP TABLE 可以将表完全删除
2. DELETE 语句会列下表(容器),而删除表中的全部数据。
drop table 会将表完全删除,删除之后,再想插入数据就必须在创建一张新的表。
delete 删除数据后,会保留表,可以再次世界使用INSERT直接插入数据。
DELETE 语句的基本语法
将表中的数据全部删除
搜索型删除
删除某些符合条件的记录
另外一些数据库(Oracle,SQL,SQL server,PostgreSQL.Mysql,DB2)中还有一个TRUNCATE 语句。
TRUNCATE 只能删除表中的全部数据。其处理速度要比DELETE快很多。实际上DELETE在DML语句中属于处理时间比较长的,因此需要删除全部数据时,使用TRUNCATE可以节省时间。
三者的区别可以参考:https://www.cnblogs.com/zhizhao/p/7825469.html
4-3 数据的更新(update语句使用方法)
搜索型UPDATE
多列更新
Update子句色set支持同时将多个列作为更新对象。
可以写为
个人感觉第一种可读性比较好。
并且第二种用法,仅在部分数据库中可以使用。
4-4事务
事务就是需要在同一个处理单元中执行的一系列更新处理的集合
事务的基本语法
标准SQL中没有定义事务的语句,而是由各个RDBMS自身定义的。
commit 提交处理
commit 是提交事务包含全部更新处理的结束指令。一旦提交就无法恢复到事务开始前的状态了。
ROLLBACK 取消处理
ROLLBACK是取消事务包含的全部更新的结束处理的指令,相当于文件中的放弃保存。一旦回滚,数据库就会恢复到事务开始之前的状态。
在这样不适用指令而悄悄开始的事务,应该如何区分?
1. 每条s q l语句就是一个事务
2. 直到用户执行CONMIT 或者ROLLBACK 为止算作一个事务
ACID特性
DBMS的事务要遵循以下四种特性。
-
原子性
原子性是指事务结束时,其包含的更新处理要不全部执行,要不完全部执行。 例如用户在一个事务中定义了两条UPDATE语句,DBMS肯定不会只执行其中一条,否则会对业务处理产生影响。
-
一致性
一致性是指事务中包含的处理要满足数据库前提设置的约束,如主键或者NOT NULL,对于事务来说,不合法的SQL会被回滚。
-
隔离性
隔离性是指保证不同事务之间互不干扰的特性。该特性保证了事务之间不会相互嵌套。在耨个事务中进行修改,在事务结束之前,对其他事务而言是不可见的。
-
持久性
指的是事务结束后(回滚或者提交),DBMS能够保证该时间点的数据状态会呗保存的特性。
保证持久性的方法根据实现的不同而不同,其中最常见的就是将事务的执行记录保存到硬盘等存储介质中(该记录称为日志)
复杂查询
5-1视图
使用视图时,并不会讲数据保存到存储设备中,而且不会将数据保存到其他地方。
使用视图的两大优点:
-
视图无需保存数据
可以节省存储设备的容量。
-
将频繁使用的select 语句保存成视图。(封装s q l)
创建视图的方法
select 语句要写在as 之后。select 居于中列的排列顺序和视图中列的排列顺序相同。
视图就是保存好的select语句
使用视图的查询
- 首先执行定义视图的select查询语句
- 根据得到的结果,在执行from子句使用视图的select语句
也就是说可以视图来创建视图。(但是要避免这种情况,因为多重视图为降低s q l的性能)
视图的限制 - 定义视图时不能使用order by
为什么不能使用order by?
因为数据行是没有顺序的
视图的限制 - 对视图的更新
- select 子句中未使用 distinct
- from 子句中只有一张表
- 未使用 group by子句
- 未使用having 子句
其实 from子句中可以使用多张表。
视图归根结底是从表中派生出来的,如果原表可以更新,那么视图中的数据也可以更新。反之,如果视图发生了改变,而原表没有进行改变更新的话,就无法保证数据的一致性了。
能够更新视图的情况
删除视图
可能存在删除以视图为基础而创建的多重视图,由于存在关联视图,可能会出现以下错误:
这时候就需要使用级联删除(CASCADE)
5-2子查询
会先执行内层的查询,在执行外层的查询。子查询的层数可以无限叠加。
子查询的名称
原则上,子查询必须设定名称(其实也可以不用),例如上图使用ProductSum作为子查询的名称。
标量子查询
标量就是单一的意思。
标量子查询必须而且只能返回一行一列的结果。
标量子查询的书写位置
标量子查询的书写位置不仅仅局限于where 子句中,通常任何可以使用单一值的位置都可以使用。
能够使用常数或者列名的地法规,无论是select子句,group b y 子句,having 子句,还是order b y 子句巨虎所有的地方都可以使用
使用标量子查询时的注意事项
该子查询绝对不能返回多行结果。比如一下这种情况就不允许发生。
关联子查询
如果需要查出各个商品种类中,高于该商品种类的平均销售单价的商品。
这样肯定是不行的。
需要使用关联子查询
这种方式会进行全表的扫描,依次判断是否满足条件。
在细分的组内进行比较时,需要使用关联子查询
关联子查询也是用来对集合进行且切分的
关联子查询和group by一样可以对集合进行切分。
内部的执行过程
结合条件一定要写在子查询中
上述s q l违反了关联名称额作用域。
具体来讲,子查询内部设定额关联名称,只能在该查询内部使用。此时外部查询无法看到p2表。
第六章 函数、谓词、case表达式
函数的种类
所谓函数就是输入某一值得到相应输出结果的功能,输入的值称为参数。输出的值称为返回值。
函数大致分为一下几种:
算数函数(用来进行数值计算的函数)
字符串函数(用来进行字符串操作的函数)
日期函数(用来进行日期操作的函数)
转换函数(用来转换数据类型和值的函数)
聚合函数(用来进行数据聚合的函数)
算数函数
+,-,*,/
abs(数值)
绝对值
MOD(被除数,除数)
取余数(s q l server 不支持该函数)
round(对象数值,保留小数的位数)
四舍五入
字符串函数
length(字符串)
获取长度
英文字母占用一个字节,汉子占用两个以上的字节。
lower(字符串)
只能针对一个英文字母使用,将字符串全都转为小写。
replace(对象字符串,替换字符串,替换后的字符串)
substring(对象字符串 from 截取位置 for 截取的字符数)
只能在mysql 和postgre sql中使用
upper(字符串)
大写转换
日期函数
current_date
当前日期
current_time
当前时间
current_timestamp
当前日期和时间
extract(日期元素 from 日期)
截取日期元素
转换函数
cast(转换的值 as 想要转换的数据类型)
COALSSCE(数据1,数据2,数据3)
将NULL值转换为其他值
返回可变参数中,左侧开始第一个不是NULL的值。参数个数是可变的,因此可以根据需求无限添加。
转换函数使用还是很频繁的,在s q l语句中将NULL转换为其他值时就会使用转换函数。之前的学习运算或者函数中含有NULL时,结果就会变成NULL。避免这种结果的函数就是COALSSCE
6-2谓词
LIKE谓词–字符串的部分一直查询
LIKE谓词更加模糊一下,当需要进行字符串的部分一直查询时需要使用该谓词。
like 主要分为三种使用方式
1. 前向一致 where str like 'ddd%'
2. 中间一致 where str like '%ddd%'
3. 后方一致 where str like '%ddd'
此外我们还可以使用_来代替%,与%不同的是,它代表了任意一个字符。
BETWEEN 范围查询
使用BETWEEN进行范围查询,
IS NULL ,IS NOT NULL —判断是否为NULL
为了选出某些值为NULL 的列的数据,不能使用=,而只能使用特定饿的谓词,IS NULL。
与此之外,想要选取NULL以外的数据时,需要使用IS NOT NULL。
IN --OR的简单用法
使用子查询来作为IN谓词的参数
EXISTS 使用方法
exists : 强调的是是否返回结果集,不要求知道返回什么,
这样
跟这样是一样的
not exists 与exists 相反,当不存在满足子查询制定条件的记录时,返回真。
CASE表达式
什么是CASE表达式?
CASE表达式是区分情况时使用的,称为(条件)分支
CASE 表达式分为简单CASE表达式和搜索CASE表达式。
WHEN 子句中的“< 求值表达式 >”就是类似“列 = 值”这样,返回 值为真值(TRUE/FALSE/UNKNOWN)的表达式。我们也可以将其看作 使用 =、!= 或者 LIKE、BETWEEN 等谓词编写出来的表达式。
CASE 表达式会从对最初的 WHEN 子句中的“< 求值表达式 >”进行 求值开始执行。所谓求值,就是要调查该表达式的真值是什么。如果结果 为真(TRUE),那么就返回 THEN 子句中的表达式,CASE 表达式的执行 到此为止。如果结果不为真,那么就跳转到下一条 WHEN 子句的求值之中。 如果直到最后的 WHEN 子句为止返回结果都不为真,那么就会返回 ELSE 中的表达式,执行终止。
CASE 表 达式在 SQL 语句执行时,也会转化为一个值。
ELSE子句也可以省略不写,这时会被默认为ELSE NULL。
CASE中的END是不能省略的。
CASE表达式的书写位置
要求效果是这样的
使用CASE可以实现行列互换
简单CASE表达式(会受到某些制约)
第七章 集合运算
7-1 表的加减法
表的加法
集合运算会去除重复的记录
集合运算的注意事项
1. 作为运算对象的记录的列数必须相同
2. 作为运算对象的记录中列的类型必须一致
3. 可以使用任何的select语句,但order by子句只能在最后使用一次
包含重复行的集合运算-ALL选项
选取表中的公共部分
INTERSECT(交集)作用与两张表,选取他们的公共记录
记录的减法
EXCEPT(差集)其语法与UNION相同。
7-2联结(以列为单位对表进行联结)
内连接(INNER JOIN)
注意点:
1. FROM 语句 此时FROM语句中有两张表
2. ON语句 连接条件
3. SELECT 中指定的列
4. 可以与WHERE连用
外联结(OUTER JOIN)
外链接要点:
1. 选取单张表中全部的内容,内连接只能选取存在于两张表中的数据,
2. 每张表都是主表吗?指定主表的关键字为le f t (左边的表为主键)和RIGHT(右边的表为主键)
对三张以上的表进行连接
交叉连接–CROSS JOIN
CROSS JOIN(笛卡尔积)
进行交叉联结时无法使用内连接和外连接中所使用的ON子句。这是因为交叉连接是对两张表中的全部记录进行交叉组合。
联结的过时语法
除法
SQL高级处理
窗口函数
窗口函数也称为OLAP函数。
OLAP是Online Analytical Processing 的简称,意思是对数据库数据进行实时分析处理
能够作为窗口函数使用的函数
- 能够作为窗口函数的聚合函数(SUM,AVG,Count,MAX,MIN)
- RANK,DENSE_RANK,ROW_NUMBER等专用窗口函数
语法的基本使用方法-RANK函数
根据不 同的商品种类(product_type),按照销售单价(sale_price)从 低到高的顺序排序
PARTITION BY能够设定排序的对象范围。
ORDER BY能够制定按照哪一列、何种顺序进行排序。
PARTITION BY在横向上对表进行分组,而ORDER BY 决定了纵向排序的规则
通过PARTITION BY分组后的记录称为窗口。
无需指定PARTITION BY
PAETITION BY 不是必须的,即使不指定也可以使用正常的使用窗口函数。
窗口函数的种类
窗口函数的适用范围
原则上窗口函数只能在SELECT子句中使用。
作为窗口函数使用的聚合函数
计算平均移动
,我们使用了ROWS 和 PRECEDING两个关键字,将框架指定为截止到之前~行,ROWS 2 PRECEDING
就是将框架指定为“截止到之前 2 行”,也就是将作为汇总对象的记录限定为如下的“最靠近的 3 行”。
这种统计方法称为平均移动。
使用关键字 FOLLOWING(“之后”)替换 PRECEDING,就可以指 定“截止到之后 ~ 行”作为框架了
将当前记录的前后座位汇总对象
同时使用 PRECEDING(“之前”)和 FOLLOWING(“之后”)关 键字来实现。
两个ORDER BY
怎样保证顺序呢?
GROUPING 运算符
ROLLUP——同事得出合计与小记
GROUPING运算符包含以下三种
- ROLLUP
- CUBE
- GROUPING SETS
从语法上来说,就是将GROUP BY子句中的聚合键清单像ROLLUP (< 列 1>,< 列 2>,…)这样使用。该运算符的作用,一言以蔽之,就 是“一次计算出不同聚合键组合的结果”。例如,在本例中就是一次计算
出了如下两种组合的汇总结果。
1 GROUP BY ()
2 GROUP BY (product_type)
1中的GROUP BY()表示没有聚合键,也就相当于没有GROUP BY 子句(这时会得到全部数据的合计行的记录),该合计行记录称为超级分组 记录
将登记日期添加到聚合件中
GROUPING --让NULL更加容易分辨
衣服分组中,小记行,与日期为NULL的行有些相似难以区分。
SQL 提供了一个用来判断超级分组记录的 NULL 的 特定函数 —— GROUPING 函数。该函数在其参数列的值为超级分组记录 所产生的 NULL 时返回 1,其他情况返回 0
CUBE用数据来搭积木
GROUPING SETS——取得期望的积木
只获取聚合的结果。
``
``
``
``
``
``
``
``
``
``
``