Mysql小记
外键约束
设置主从表主键、外键(主键所在为主表,外键所在为从表)的时候,注意外键约束属性
CASCADE: 父表delete/updatate时,子表同步delete/update关联记录SET NULL: 父表delete/update, 子表将关联记录的关键字段所在列设为null, 因此设计子表时外键不能设为not nullRESTRICT: 如果子表中有关联父表的记录,那么想要删除父表记录时会不允许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,否则返回0IFNULL(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才不计