Mysql小记
外键约束
设置主从表主键、外键(主键所在为主表,外键所在为从表)的时候,注意外键约束属性
CASCADE
: 父表delete
/updatate
时,子表同步delete
/update
关联记录SET NULL
: 父表delete/update
, 子表将关联记录的关键字段所在列设为null
, 因此设计子表时外键不能设为not null
RESTRICT
: 如果子表中有关联父表的记录,那么想要删除父表记录时会不允许NO ACTION
: 同RESTRICT
,子表有匹配记录就不允许父表update
/delete
但是,目前其实很多场景不需要数据库中的真实外键,只用设计逻辑外键就行
真实外键存在的情况下:
- 一是不方便数据测试
- 二是高并发造成死锁
- 三是一致性事务完全交给数据库处理,很多时候资源占用高
关键词查询/模糊匹配
涉及关键字查询或者模糊匹配的时候可以用 通配符模糊匹配、内置函数检索、正则匹配查询、全文索引
- 通配符有
%
_
加上like
操作符 - 内置函数有
instr()
locate()
position()
等,语法接近 mysql
支持绝大部分正则表达式功能,基于regexp
/rlike
等,基本涵盖所有需求- 全文索引是
mysql
索引中的一种,支持字段格式包括char
、varchar
、text
,语法为match(#{字段名}) against(#{keyWord})
。若不存在任何匹配结果,返回0
;否则根据匹配次数多少和位置先后返回一个匹配度。
布尔值
true, false, 1 , 0
mysql
中没有内置布尔类型,使用tinyint(1)
来作为其等效进行存储,同时提供boolean
和bool
作为tinyint(1)
的同义词。0
被认为是false
,非零值
被认为true
。而默认使用true
和false
时,计算值为1
和0
NULL值与字符串空值
一般来说,''
空值说的是字符串是空的,也就是个空串;而NULL
值的是一个字段未知,即unkonwn
,两者不能混为一谈
特别注意,针对于NULL值是有特殊的处理运算符的:IS NULL
, IS NOT NULL
,所以用=
、!=
、>
、<
是不行的;
但是有一个特例:<=>
运算,形如exp <=> NULL
,如果exp
的值是NULL
,会返回1
另外,有一些针对NULL
的函数:
IFNULL(exp)
: 如果exp
的值为NULL
,则返回1
,否则返回0
IFNULL(exp1, exp2)
: 如果exp1
是NULL
的话那么返回exp2
的值,否则返回exp1
的值NULLIF(exp3, exp4)
:如果exp3 = exp4
成立,那么返回NULL
值,否则返回exp1
值
去重
一般常用的去重方法有distinct
和group by
distinct
:
用于select
语句开头
- 如果去重列具有
NULL
值,会保留一个NULL
值并删除其他 - 多列去重的条件下,只有所有指定列的的列信息都相同才会认为此信息重复
group by`:
通常和聚合函数如count()
、max()
等一起使用,放在where
条件之后
- 可以单列/多列去重(
mysql5.7
之后默认SQL
模式包括ONLY_FULL_GROUP_BY
,默认要求使用group by
时去重列即查询列。可以打破,重新设置) - 去重的时候,
group by
会根据去重字段分组,如果数据相同那么就会分到一个组里面,再返回每个组的第一条数据,完成去重
效率的话,mysql8.0
之前group by
有个隐式排序:
在Mysql8.0之前,Group by会默认根据作用字段(Group by的后接字段)对结果进行排序。在能利用索引的情况下,Group by不需要额外进行排序操作;但当无法利用索引排序时,Mysql优化器就不得不选择通过使用临时表然后再排序的方式来实现GROUP BY了。且当结果集的大小超出系统设置临时表大小时,Mysql会将临时表数据copy到磁盘上面再进行操作,语句的执行效率会变得极低。这也是Mysql选择将此操作(隐式排序)弃用的原因。
所以,从8.0开始,在语义相同,不论有无索引的情况下二者效率相同;
在8.0之前,如果没有索引,group by
会进行隐式排序,触发filesort
,效率低
另外: 有的场景需要针对去重之后的数据作统计,可以使用count()
函数,以去重字段为计数条件
连接查询
一般连接查询的语法:
1 | select column from table1 #{连接方式} table2 on #{连接条件} |
内连接inner join
这种方式是提取两张表的共同点,即交集;且是系统默认的连接方式,可以省略inner
左连接left join
此方式查询左表table1
的的全部内容以及右表table2
中符合条件的记录,如果table2
中有些字段没有匹配到会默认使用NULL
补充代替
右连接right join
同理,查询右表table2
的全部内容和左表table1
符合条件记录,NULL
补充未匹配上字段
连接查询后面时常还会加另外的限制条件,where
、having
等
using关键字
连接查询时可以用on
作为连接条件,同样也可以用using
,两者效果一致:
using(#{某个字段})
=
on table1.#{同名字段} = talbe2.#{同名字段}
注意:
using
关键字针对的是同名字段- 使用
using
之后在拼接表中会自动合并对应字段为一个 using
支持同时使用多个字段
count()函数
条件计数的话里面经常和别的函数一起用,比方说if
,针对某个字段的某个条件计数可以写成:
1 | count(if(${condition}, 1, null)) |
这样写的原因是:coount()
只要该行有值就会统计,null
才不计