全面、详细的SQL学习指南(MySQL方向)

文章目录

  • 数据类型
    • 数字类型
    • 字符串类型
    • 时间类型
    • 数据类型的默认值
  • 运算符
    • 算术运算符
    • 关系运算符
    • 逻辑运算符
  • 函数
    • 单行函数
    • 聚合函数
    • 窗口函数
  • DDL
    • 数据库管理
    • 表管理
    • 约束
      • 主键约束
      • 外键约束
      • 唯一约束
      • check约束
    • 计算列
    • 视图
    • 存储过程
      • 用户变量
        • 会话用户变量
        • 局部变量
      • 流程控制
      • 定义条件与处理程序
      • 游标
    • 触发器
    • 索引管理
  • DML
    • 插入数据
    • 更新数据
    • 删除数据
    • 基础查询
    • 连接查询
      • 笛卡尔积
      • 连接分类
        • 内连接
        • 外连接
    • 子查询
    • 联合查询
    • 查询语句的执行流程
  • DCL
    • 用户管理
    • 权限管理
    • 角色管理

数据类型

数字类型

整数类型

在计算时,mysql使用bigint作为底层计算的类型。

名称 所占位数
tinyint 8
smallint 16
mediumint 24
int 32
bigint 64

定点数类型

在计算时,mysql以65位的精度完成。

名称 所占位数
decimal(M,N) M+2

浮点数类型

在计算时,mysql使用double作为底层计算的类型。

名称 所占位数
float 32
double 64

数字类型的属性

属性 说明
unsigned 整数类型可以使用此属性变更为无符号的形式,以达到扩大范围的目的
auto_increment 整数类型可以使用该属性,但该属性不支持列的负值。自增长列约束的列必须是主键列或唯一键列,如果自增列指定了 0 和 null,会在当前最大值的基础上自增;如果自增列手动指定了具体值,直接赋值为具体值。

字符串类型

字符串类型必须使用单引号表示。

字符单位字符串类型

名称 说明
char(M) M表示该类型的长度,M的范围为0~255,char类型的列会截断值的尾空格
varchar(M) M表示该类型的最大长度,M的范围为0~65535
tinytext 最大长度为255
text 最大长度为65535
mediumtext 最大长度为16,777,215
longtext 最大长度为4,294,967,295

字节单位字符串类型

此类字符串主要存储一些二进制数据,比如可以存储图片、音频和视频等二进制数据。在实际工作中,往往不会在MySQL数据库中存储大对象数据,通常会将图片、音频和视频文件存储到服务器的磁盘上 ,并将图片、音频和视频的访问路径存储到MySQL中。

名称 说明
binary(M) M表示该类型的长度,M的范围为0~255
varbinary(M) M表示该类型的最大长度,M的范围为0~65535
tinyblob 最大长度为255
blob 最大长度为65535
mediumblob 最大长度为16,777,215
longblob 最大长度为4,294,967,295

时间类型

时间类型的数据必须使用单引号表示。

名称 格式 所占位数
year yyyy 8
time hh:mm:ss 24
date yyyy-mm-dd 24
datetime yyyy-mm-dd hh:mm:ss 64
timestamp yyyy-mm-dd hh:mm:ss 32

时间类型的属性

属性 说明 是否即将废弃
on update < time > datetime和timestamp类型可以使用该属性,使用该属性的列更新时值更改为time

数据类型的默认值

显式默认值

default用于显式指定数据类型的默认值,如果默认值是一个表达式,需要用括号括起来,blob和text类型的默认值必须使用括号括起来。在表达式中可以使用字面量、内置函数和运算符。

default <const>|(<expression>)

隐式默认值

如果没有显式的指定默认值,MySQL会通过如下步骤确定列的默认值:

  • 如果列可以接受null作为值,则使用null作为默认值。
  • 如果该列定义时使用了not null,那么mysql将该列定义为没有默认值的列,在添加或修改数据时必须传入该列的值。

运算符

算术运算符

算术运算符主要用于数学运算,其可以连接运算符前后的两个数值或表达式,对数值或表达式进行加(+)、减(-)、乘(*)、除(/)和取模(%)运算。

  • 加、减运算规则:一个整数类型和一个整数加减结果还是一个整数;一个整数类型的值对浮点数进行加法和减法操作,结果是一个浮点数;加只表示数值相加,如果遇到非数值类型,先尝试转成数值,如果转失败,就按0计算。
  • 乘、除运算规则:一个数乘以整数1和除以整数1后仍得原数;一个数乘以浮点数1和除以浮点数1后变成浮点数,数值与原数相等;一个数除以整数后,不管是否能除尽,结果都为一个浮点数;一个数除以另一个数,除不尽时,结果为一个浮点数,并保留到小数点后4位;一个数除以0为NULL。

关系运算符

关系运算符用来对表达式左边的操作数和右边的操作数进行比较,比较的结果为真则返回1,比较的结果为假则返回0,其他情况则返回NULL。

  • 等号运算规则:如果等号两边的值都是字符串则MySQL会按照字符串进行比较;如果等号两边的值都是整数则MySQL会按照整数来比较;如果等号两边的值一个是整数,另一个是字符串,则MySQL会将字符串转化为数字进行比较;如果等号两边的值、字符串或表达式中有一个为NULL,则比较结果为NULL。
  • 安全等号运算规则:安全等号运算符与等号的作用是相似的, 唯一的区别 是安全等号可以用来对NULL进行判断。在两个操作数均为NULL时,其返回值为1,当一个操作数为NULL时,其返回值为0L。
运算符 说明
>、>=、<、<=、=、<> -
<=> NULL 安全等号
between and 一个值是否在一个值范围内
is null 空值测试
is not null 非空值值测试
like 简单的模式匹配
regexp 正则表达式
in() 一个值是否在一组值内

like通配符

通配符 说明
% %表示任何字符出现任意次数,虽然似乎%通配符可以匹配任何东西,但有一个例外,即NULL。尾空格可能会干扰通配符匹配。
_ 匹配单个字符

正则表达式

特殊符号 说明
. 匹配任一字符
| 正则表达式or操作
[a,c,b] 匹配a或b或c
[0-9] 匹配0-9中的字符
\ 转义
* 0个或多个匹配
+ 1个或多个匹配(等于{1,})
? 0个或1个匹配(等于{0,1})
{n} 指定数目的匹配
{n,} 不少于指定数目的匹配
{n,m} 匹配数目的范围(m不超过255)
^ 文本的开始
$ 文本的结尾

逻辑运算符

逻辑运算符主要用来判断表达式的真假,在MySQL中,逻辑运算符的返回结果为1、0或者NULL。

运算符 说明
and
not
or
xor 异或

函数

根据参数和返回值可以将函数分为单行函数和多行函数:
全面、详细的SQL学习指南(MySQL方向)_第1张图片

单行函数

单行函数可以嵌套使用。

数学

函数 说明
ABS(x) 返回x的绝对值
POW(x,y) 返回x的y次方
EXP(X) 返回e的X次方
SQRT(x) 返回x的平方根。当X的值为负数时,返回NULL
LN(X) 返回以e为底的X的对数,当X <= 0 时,返回NULL
LOG10(X) 返回以10为底的X的对数,当X <= 0 时,返回NULL
LOG2(X) 返回以2为底的X的对数,当X <= 0 时,返回NULL
PI() 返回圆周率的值
MOD(x,y) 返回X除以Y后的余数
RAND(x) 返回0~1的随机值,其中x的值用作种子值,相同的X值会产生相同的随机数
ROUND(x) 返回一个对x的值进行四舍五入后,最接近于X的整数
ROUND(x,y) 返回一个对x的值进行四舍五入后最接近X的值,并保留到小数点后面Y位
TRUNCATE(x,y) 返回数字x截断为y位小数的结果

最大值最小值

函数 说明
CEILING(x) 返回大于或等于某个值的最小整数
FLOOR(x) 返回小于或等于某个值的最大整数
LEAST(e1,e2,e3…) 返回列表中的最小值
GREATEST(e1,e2,e3…) 返回列表中的最大值

进制转换

函数 说明
BIN(x) 返回x的二进制编码
HEX(x) 返回x的十六进制编码
OCT(x) 返回x的八进制编码
CONV(x,f1,f2) 返回f1进制数变成f2进制数

字符串

MySQL中,字符串的位置是从1开始的。

函数 说明
CHAR_LENGTH(s) 返回字符串s的字符数
LENGTH(s) 返回字符串s的字节数,和字符集有关
CONCAT(s1,s2,…,sn) 连接s1,s2,…,sn为一个字符串
CONCAT_WS(x,s1,s2,…,sn) 同上,但是每个字符串之间要加上x
INSERT(str, idx, len,replacestr) 将字符串str从第idx位置开始,len个字符长的子串替换为字符串replacestr
REPLACE(str, a, b) 用字符串b替换字符串str中所有出现的字符串a
UPPER(s) 字符串s的所有字母转成大写字母
LOWER(s) 将字符串s的所有字母转成小写字母
LEFT(str,n) 返回字符串str最左边的n个字符
RIGHT(str,n) 返回字符串str最右边的n个字符
LPAD(str, len, pad) 用字符串pad对str最左边进行填充,直到str的长度为len个字符
RPAD(str ,len, pad) 用字符串pad对str最右边进行填充,直到str的长度为len个字符
LTRIM(s) 去掉字符串s左侧的空格
RTRIM(s) 去掉字符串s右侧的空格
TRIM(s) 去掉字符串s开始与结尾的空格
TRIM(s1 FROM s) 去掉字符串s开始与结尾的s1
TRIM(LEADING s1 FROM s) 去掉字符串s开始处的s1
TRIM(TRAILING s1 FROM s) 去掉字符串s结尾处的s1
REPEAT(str, n) 返回str重复n次的结果
SPACE(n) 返回n个空格
STRCMP(s1,s2) 比较字符串s1,s2的ASCII码值的大小
ELT(m,s1,s2,…,sn) 返回指定位置的字符串,如果m=1,则返回s1,如果m=2,则返回s2,如果m=n,则返回sn
FIELD(s,s1,s2,…,sn) 返回字符串s在字符串列表中第一次出现的位置
FIND_IN_SET(s1,s2) 返回字符串s1在字符串s2中出现的位置。其中,字符串s2是一个以逗号分隔的字符串
REVERSE(s) 返回s反转后的字符串
NULLIF(value1,value2) 比较两个字符串,如果value1与value2相等,则返回NULL,否则返回value1

时间与日期

函数 说明
CURDATE() 返回当前日期
CURTIME() 返回当前时间
NOW() 返回当前系统日期和时间
UNIX_TIMESTAMP() 以UNIX时间戳的形式返回当前时间。SELECT UNIX_TIMESTAMP() ->1634348884
UNIX_TIMESTAMP(date) 将时间date以UNIX时间戳的形式返回。
FROM_UNIXTIME(timestamp) 将UNIX时间戳的时间转换为普通格式的时间
YEAR(date) / MONTH(date) / DAY(date) 返回具体的日期值
HOUR(time) / MINUTE(time) /SECOND(time) 返回具体的时间值
MONTHNAME(date) 返回月份:January,…
DAYNAME(date) 返回星期几:MONDAY,TUESDAY…SUNDAY
WEEKDAY(date) 返回周几,注意,周1是0,周2是1,。。。周日是6
QUARTER(date) 返回日期对应的季度,范围为1~4
WEEKOFYEAR(date) 返回一年中的第几周
DAYOFYEAR(date) 返回日期是一年中的第几天
DAYOFMONTH(date) 返回日期位于所在月份的第几天
DAYOFWEEK(date) 返回周几,注意:周日是1,周一是2,。。。周六是7

流程控制

函数 说明
IF(value,value1,value2) 如果value的值为TRUE,返回value1,否则返回value2
IFNULL(value1, value2) 如果value1不为NULL,返回value1,否则返回value2
CASE WHEN 条件1 THEN 结果1 WHEN 条件2 THEN 结果2… [ELSE resultn] END 相当于Java的if…else if…else…
CASE expr WHEN 常量值1 THEN 值1 WHEN 常量值1 THEN值1 … [ELSE 值n] END 相当于Java的switch…case…

聚合函数

聚合函数不可以嵌套使用,在不使用group by子句的情况下,聚合函数默认将整个表看作一组,否则将group by子句的分组看作一组。

函数 说明
AVG() 返回某列的平均值
COUNT() 返回某列的行数
MAX() 返回某列的最大值
MIN() 返回某列的最小值
SUM( ) 返回某列值之和

窗口函数

窗口函数可以对数据进行分组,并对分组后组中的数据进行统计排序。聚合函数也可以使用以下语法,这意味着对每个组聚合。

<funName> over(partition by <rowName> order by <rowName> asc|desc)
函数 说明
row_number() 对各组数据进行顺序序号显式
rank() 对各组数据进行顺序序号显式,排序行重复的序号相同,并且会跳过重复的序号。
dense_rank() 对各组数据进行顺序序号显式,排序行重复的序号相同,不会跳过重复的序号。

DDL

MySQL8支持DDL原子化,即 DDL操作要么成功要么回滚 。DDL操作回滚日志写入到data dictionary数据字典表mysql.innodb_ddl_log(该表是隐藏的表,通过show tables无法看到)中,用于回滚操作。而在MySQL5中,DDL是不支持原子化的,且在执行后不能回滚。

数据库管理

查询所有数据库

show databases;

查看当前正在使用的数据库

select database()

查看数据库的创建信息

show create database

使用数据库

use <databaseName>;

创建数据库

create database [if not exists] <databaseName>
|character set <charsetName>
|collate <collateName>
|encryption <'Y'|'N'>

删除数据库

drop database [if exists]  <databaseName>

修改数据库结构

alter database <databaseName>
|character set <charsetName>
|collate <collateName>
|encryption <'Y'|'N'>
|read only <0|1>

表管理

查询所有表

show tables;

查看表结构

desc <tableName>

创建表

create table [if not exists] <tableName>
(
	<columnName> <columnType> <attribute>
	<constraintDefinition> 
	<indexDefinition>
)[engine=engineName]

删除表

drop table [if exists] <tableName>

修改表结构

mysql执行大部分修改表的操作都是用新的结构创建一个新表,从旧表中查出所有数据插入新表,然后删除旧表。

alter table <tableName>
|add column <columnName> <columnDefinition> [first|after columnName] //添加列
	 index <idnexName> //添加索引
	 constraint <constraintDefinition> 
|drop column <columnName> //删除列
	  index <idnexName>//删除索引
	  constraint <constraintName>
|change column <oldColumnName> <newColumnName> <columnDefinition> [first|after columnName]//改名
|modify column <columnName> <columnDefinition>

重命名表

rename table <oldTableName> to <newTableName>

复制表

create table <tableName> like <tableName> #复制表结构
create table <tableName> select * from <databaseName.tableName> #复制表结构和数据

清空表

truncate table <tableName> 

约束

约束用于限制表中的字段,从而进一步确定数据的一致性和准确性。

主键约束

  • 每一个表中只能有一个主键索引。
  • 主键索引可以由多个列组成,其中所有的列都被定义为not null,并且组合的值不允许重复。
  • MySQL的主键名总是primary,就算自己命名了主键约束名也没用。
  • 当创建主键约束时,系统默认会在所在的列或列组合上建立对应的主键索引。
  • 如果删除主键约束了,主键约束对应的索引就自动删除了。
  • 删除主键约束后,非空还存在。
constraint <primaryKeyName> primary key (columnNameList)

外键约束

  • 外键约束必须引用主表中的主键
  • 外键不能跨引擎引用其他主表的键
  • 在创建外键约束时,如果不给外键约束命名,默认名不是列名,而是自动产生一个外键名。
  • 当主表的记录被从表参照时,主表的记录将不允许删除,如果要删除数据,需要先删除从表中依赖该记录的数据,然后才可以删除主表的数据。
  • 从表的外键列与主表被参照的列名字可以不相同,但是数据类型必须一样,逻辑意义一致。
  • 当创建外键约束时,系统默认会在所在的列上建立对应的普通索引。
  • 删除外键约束后,必须手动 除对应的索引。
constraint <foreignKeyName> foreign key (columnName) references <foreignKeyTableName> (foreignKeyColumnNameList) 

唯一约束

  • 唯一约束可以是某一个列的值唯一,也可以多个列组合的值唯一。
  • 唯一性约束允许列值为空。
  • 如果创建唯一约束时未指定名称,如果是单列,就默认和列名相同;如果是组合列,那么默认和括号中排在第一个的列名相同。
  • MySQL会给唯一约束的列上默认创建一个唯一索引。
  • 删除唯一约束只能通过删除唯一索引的方式。
constraint [uniqueName] unique (columnNameList)//表级别写法

check约束

  • 限制列取值在规定范围内
  • check约束不能引用具有Tauto_increment属性的列
constraint [checkName] check(expression) 

计算列

计算列是指某列的值可以通过别的列计算得来,create tablealter table中都支持增加计算列:

generat always as(expression) vtriual

视图

  • 视图建立在已有表的基础上, 视图赖以建立的这些表称为基表,它是一种虚拟表 ,本身不具有数据,占用很少的内存空间。
  • 视图一方面可以帮我们使用表的一部分而不是所有的表,另一方面也可以针对不同的用户制定不同的查询视图。
  • 视图的创建和删除只影响视图本身,不影响对应的基表。但是当对视图中的数据进行增加、删除和修改操作时,数据表中的数据会相应地发生变化,反之亦然。
  • 在定义视图的时候指定了algorithm=temptable,视图将不支持insertdelete操作。
  • 视图中不包含基表中所有被定义为非空又未指定默认值的列,视图将不支持insert操作
  • 在定义视图的select语句中使用了join联合查询 ,视图将不支持insertdelete操作。
  • 在定义视图的SELECT语句后的字段列表中使用了 数学表达式 或 子查询 ,视图将不支持INSERT,也不支持UPDATE使用了数学表达式、子查询的字段值;
  • 在定义视图的SELECT语句后的字段列表中使用 DISTINCT 、 聚合函数 、GROUP BY 、 HAVING 、UNION 等,视图将不支持INSERT、UPDATE、DELETE;
  • 在定义视图的SELECT语句中包含了子查询,而子查询中引用了FROM后面的表,视图将不支持INSERT、UPDATE、DELETE;
  • 视图定义基于一个 不可更新视图 ;
  • 如果实际数据表的结构变更了,我们就需要及时对相关的视图进行相应的维护。

查看视图

show tables

查看视图结构

desc <viewName>

创建视图

create view [algorithm=undefined|merge|temptable] <viewName>
as 
<selectExpression>
[with [cascaded|local]check option]

修改视图

alter view <viewName>
as
<selectExpression>

删除视图

drop view [fi exists] <viewName>

存储过程

存储过程是对一系列SQL语句的封装。存储过程有三种参数类型:

  • in:当前参数为输入参数,存储过程只是读取这个参数的值。
  • out:当前参数为输出参数,执行完成之后,调用这个存储过程的客户端或者应用程序就可以读取这个参数返回的值。
  • inout:当前参数既可以为输入参数,也可以为输出参数。
create procedure <procedureName> (in|out|inout <param> <type>,...)
[
	language sql #说明存储过程执行体是由SQL语句组成的,当前系统支持的语言为SQL。
	deterministic|not deterministic #指明存储过程执行的结果是否确定。
	#contains sql表示当前存储过程的子程序包含SQL语句,但是并不包含读写数据的SQL语句
	#no sql表示当前存储过程的子程序中不包含任何SQL语句
	#reads sql data表示当前存储过程的子程序中包含读数据的SQL语句
	#modifies sql data表示当前存储过程的子程序中包含写数据的SQL语句
	#默认情况下,系统会指定为contains sql
	contains sql|no sql|reads sql data|modifies sql data
	#definer表示只有当前存储过程的创建者或者定义者才能执行当前存储过程
	#invoker表示拥有当前存储过程的访问权限的用户能够执行当前存储过程
	#默认指定值为definer
	sql security [definer|invoker]
	comment <comment> #注释信息
]
begin
	<SQL>
end 

存储过程中的SQL以分号结束,如果使用MySQL客户端程序定义一个存储程序就会出现问题。因为在默认情况下,MySQL本身将分号识别为语句分隔符,因此必须使用以下语句临时重新定义分隔符,以使MySQL将整个存储的程序定义传递给服务器:

delimiter <identityDelimiter>

存储函数类似于存储过程,存储函数可以放在查询语句中使用,存储过程不行。但是存储过程的功能更加强大,包括能够执行对表的操作和事务操作。不建议使用存储函数。

create function <functionName> (<param> <type>) returns <type>
[
	language sql
	deterministic|not deterministic 
	contains sql|no sql|reads sql data|modifies sql data
	sql security [definer|invoker]
	comment <comment> 
]
begin
	<SQL>
	return <expr>
end 

查询

show procedure status
|like <procedureName>

调用

call <procedureName>(param)

删除

drop procedure [if exists] <procedureName>

修改

alter procedure <procedureName>
[
	contains sql|no sql|reads sql data|modifies sql data
	sql security [definer|invoker]
	comment <comment> 
]

用户变量

用户变量是用户自定义的变量,在MySQL 中的用户变量以 一个@开头。用户变量又分为会话用户变量和局部变量两种 。

会话用户变量

会话用户变量作用于当前连接,且在连接断开时自动清除,并且在再次连接时也不再出现。

set @<varName>:=<value> #声明
select <selectList> into @<varName> [from...] #赋值
select @<varName> #查看

局部变量

局部变量只在存储过程和存储函数中的beginend语句块中有效。

declare <varName> <type> [default <value>]  #声明
set <varName>:=<value> #赋值
select <selectList> into <varName> [from...] #赋值

流程控制

流程控制语句只能在存储过程中使用。

if语句

if (condition) then
	<something>
elseif (condition) then
	<something>
else
	<something>
end if;

case语句

case <expr>
	when <value1> then <something>
	when <value2>  then <something>
    else <something>
end case;

loop语句

[loopLabel:]loop
	<something>
end loop [loopLabel]

while语句

[whileLebel:] while <condition> do
	<something>
end while [whileLabel];

repeat语句

[repeatLabel:] repeat
	<something>
until <condition>;
end repeat [repeatLabel];

leave语句

leave <labelName> #类似于break

iterate语句

iterate <labelName> #类似于continue

定义条件与处理程序

定义条件就是给MySQL中的错误码命名,它将一个错误名字和指定的错误条件关联起来。

declare <errorName> condition for <errorCode>

其中errorCode可以是MySQL_error_code数值类型错误代码或sqlstate_value长度为5的字符串类型错误代码,它俩都可以表示MySQL的错误。处理程序用于处理SQL执行过程中发生的某种类型的错误。

declare <handlerMode> handler for <errorType> <handlerExpr>

handlerMode有三个取值:

  • continue:表示遇到错误不处理,继续执行。
  • exit:表示遇到错误马上退出。
  • undo:表示遇到错误后撤回之前的操作,MySQL中暂时不支持这样的操作。

errorType有以下取值:

  • errorName:定义条件定义的错误名称。
  • sqlwarning:匹配所有以01开头的sqlstate错误代码。
  • not found:匹配所有以02开头的sqlstate错误代码。
  • sqlexception:匹配所有没有被not found和sqlexception捕获的sqlstate错误代码。

handlerExpr:如果出现errorType中的条件,则采用对应的处理方式,并执行handlerExpr。handlerExpr可以是简单的语句或者是BEGIN ... END编写的复合语句。

游标

游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制,尽管游标能遍历结果中的所有行,但它一次只指向一行。游标可以在存储过程和函数中使用。游标声明必须出现在处理程序声明之前以及变量和条件声明之后。

声明

declare <cursorName> cursor for <selectStatement>

打开

open <cursorName>

取值

fetch <cursorName> into <varName>

关闭

close <cursorName>

触发器

触发器可以由insert 、 update、 delete事件来触发并自动执行相应的操作。

create trigger <triggerName> 
[before|after] [insert|update|delete] on <tableName>
for each row 
<SQL>#可以是简单的语句或者是`BEGIN ... END`编写的复合语句

查看触发器

show triggers #查看所有触发器
show create trigger <triggerName> #查看某个触发器的定义

删除触发器

drop trigger [if exists] <triggerName>

索引管理

查看所有索引

show index from <tableName> 

创建索引

create [indexType] index <indexName> on <tableName> 
|(<columnName> [asc|desc]) 
|(<columnName>(length) [asc|desc])
|(<columnName1> [asc|desc],<columnName2> [asc|desc])

删除索引

drop index <indexName> on <tableName> 

DML

数据库操作语言,用于添加、删除、更新和查询数据库记录,并检查数据完整性。

插入数据

插入语句中columnNames可以省略,但是它们必须被设置为可以是null或有默认值。columnValues中的值必须和columnNames或列一一对应。

insert into <tableName> (columnNames)
values (columnValues1),(columnValues2)
|select (columnNames>) from tableName #如果插入检索出来的值那么columnNames必须和插入表的列名一至,顺序可以不同。

更新数据

update <tableName>
set <columnName>=<columnValue>,...
|where <condition>
|limit 

删除数据

delete from <tableName>
|where <condition>
|limit

基础查询

//distinct要放在所有列名前面并且它对selectList自左向右去重
//as为列名别名
select [distinct] <selectList> [as alias]
from <tableName>
|where <condition>
|group by <groupList> //在SELECT列表中所有未包含在聚合函数中的列都应该包含在 group by子句中,包含在group by子句中的列不必包含在SELECT 列表中。
|having <condition> //分组后筛选
|order by <orderList> [asc|desc] //排序列表可以是多个字段,只有当第一个字段有重复值时其它字段才会起作用。asc升序,默认行为。desc降序。它们只应用到直接位于其前面的字段。
|limit <startColumn>,<count> //用于限制结果数目,返回从第startColumn行开始的count行,limit必须位于order by之后。
|limit <count> //返回结果不超过count行

连接查询

笛卡尔积

笛卡尔乘积是一个数学运算。假设我有两个集合 X 和 Y,那么 X 和 Y 的笛卡尔积就是 X 和 Y 的所有可能组合。在SQL中,笛卡尔积也称为交叉连接,它的作用就是可以把任意表进行连接,即使这两张表不相关。为了避免笛卡尔积,需要在连接时加入有效的连接条件,个表相连至少要有n-1个连接条件。

连接分类

内连接

合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行。

select <selectList> 
from <tableName>
innor join <tableName>
on <condition>

外连接

两个表在连接过程中除了返回满足连接条件的行以外还返回从表中不满足条件的行 ,这种连接称为外连接。没有匹配的行时, 从表中相应的列为NULL。如果连接条件中左边的表称为主表 ,右边的表称为从表,则是左外连接。

select <selectList> 
from <tableName>
left join <tableName>
on <condition>

如果连接条件中左边的表称为从表 ,右边的表称为主表,则是右外连接。

select <selectList> 
from <tableName>
right join <tableName>
on <condition>

如果连接条件中左边的表和右边的表互为主从表 ,则是满外连接。

select <selectList> 
from <tableName>
full join <tableName>
on <condition>

全面、详细的SQL学习指南(MySQL方向)_第2张图片

子查询

当一个查询语句中又嵌套了另一个查询时,被嵌套的查询语句被称为子查询,按照返回的结果集可以将子查询分类如下:

  • 标量子查询:返回一个单一值的子查询
  • 行子查询:返回一条记录的子查询
  • 列子查询:返回多个列值的子查询
  • 表子查询:返回一个表的子查询

按照与外层查询的关系可以将子查询分类如下:

  • 不相关子查询:子查询可以单独运行出来,不依赖外层查询的值
  • 相关子查询:子查询的执行需要依赖外层查询的值。

使用子查询时有如下限制:

  • 子查询必须用小括号括起来
  • 在select子句中的子查询必须是标量子查询
  • 对于in、any和all子查询来说,子查询不能有limit子句
  • 不能在一条语句中增删改某个表的记录时,同时还对该表进行子查询。
select <selectList>
from <tableName>
where <operand> <opterator|in|any|all>|<exists>
(subSelect)

联合查询

当查询结果来自于多张表,但是这些表之间没有关联,这时应该使用联合查询。在联合查询中查询语句的查询列表必须相同,否则没有意义。联合查询的结果会自动去重,如果不想去重可以使用union all进行联合查询。

select <selectList>
from <tableName>
union [all]
select <selectList>
from <tableName>

查询语句的执行流程

MySQL执行一条SQL的过程如下:

  • 客户端发送一条SQL给服务器
  • 服务器进行SQL解析、预处理,再由优化器成成对应的执行计划。
  • mysql根据优化器生成的执行计划,调用存储引擎的API来执行查询。
  • 将结果返回给客户端。

全面、详细的SQL学习指南(MySQL方向)_第3张图片

各个SQL子句的执行顺序如下:

  • from
  • join
  • on
  • where
  • group by
  • having
  • select
  • distinct
  • order by
  • limit

执行引擎先进行from阶段。在这个阶段,如果是多张表联查,还会经历下面的几个步骤:

  • 首先先通过交叉连接求笛卡尔积,相当于得到虚拟表 vt1-1
  • 通过on进行筛选,在虚拟表 vt1-1 的基础上进行筛选,得到虚拟表 vt1-2
  • 添加外部行。如果我们使用的是左连接、右链接或者全连接,就会涉及到外部行,也就是在虚拟表 vt1-2 的基础上增加外部行,得到虚拟表 vt1-3

如果我们操作的是两张以上的表,还会重复上面的步骤,直到所有表都被处理完为止。这个过程得到是我们的原始数据。当我们拿到了查询数据表的原始数据,也就是最终的虚拟表 vt1 ,就可以在此基础上进行where阶段。在这个阶段中,会根据 vt1 表的结果进行筛选过滤,得到虚拟表 vt2 。然后进入第三步和第四步,也就是grouphaving阶段 。在这个阶段中,实际上是在虚拟表 vt2 的基础上进行分组和分组过滤,得到中间的虚拟表 vt3vt4 。当我们完成了条件筛选部分之后,就可以筛选表中提取的字段,也就是进入到selectdistinct阶段 。首先在select阶段会提取想要的字段,然后在distinct阶段过滤掉重复的行,分别得到中间的虚拟表vt5-1vt5-2 。当提取了想要的字段数据之后,就可以按照指定的字段进行排序,也就是group by阶段 ,得到虚拟表 vt6 。最后在 vt6 的基础上,取出指定行的记录,也就是limit阶段 ,得到最终的结果,对应的是虚拟表vt7

DCL

数据控制语言,用于定义数据库、表、字段、用户的访问权限和安全级别。

用户管理

MySQL用户账号和信息存储在名为mysql的数据库中。用户定义为user@hosthost用于约束用户可以在哪台主机灯枯,如果不指定主机名,则使用默认的主机名%

查询用户

select user from user

创建用户

create user <userName>@<hostName> identified by <pwd>

重命名

rename user <oldName>@<oldHost> to <newName>@<newHost>

修改密码

set password for userName='newPassword';

删除用户

drop user <userName>

权限管理

MySQL将权限信息存储到mysql数据库的以下表中:

说明
user 记录用户账号和权限信息
db 记录用户对某个数据库的操作权限
tables_priv 记录用户对某个表的操作权限
columns_priv 记录用户对某个表某一列的操作权限
procs_priv 记录用户对存储过程和存储函数设置操作权限

当用户试图连接MySQL服务器时,服务器基于user表对用户的身份进行验证来确定接受或者拒绝连接。一旦建立连接,MySQL会检查此连接上的每个请求要执行什么操作、是否有足够的权限来执行它。确认权限时,MySQL首先 检查user表 ,如果指定的权限没有在user表中被授予,那么MySQL就会继续检查db表 ,db表是下一安全层级,其中的权限限定于数据库层级,在该层级的SELECT权限允许用户查看指定数据库的所有表中的数据;如果在该层级没有找到限定的权限,则MySQL继续 检查tables_priv表 以及 columns_priv表 ,如果所有权限表都检查完毕,但还是没有找到允许的权限操作,MySQL将 返回错误信息 ,用户请求的操作不能执行,操作失败。权限控制主要是出于安全因素,因此需要遵循以下几个 经验原则 :

  • 只授予能 满足需要的最小权限 ,防止用户干坏事。
  • 创建用户的时候 限制用户的登录主机 ,一般是限制成指定IP或者内网IP段。
  • 为每个用户 设置满足密码复杂度的密码 。
  • 定期清理不需要的用户 ,回收权限或者删除用户。

查看所有权限

show privileges

查看用户权限

show grants for <userName>@<hostName>

赋予用户权限

grant 
<grantName>|all privileges on <dattaBaseName>.<tableName>
to <userName>@<hostName>

撤销用户权限

revoke 
<grantName>|all privileges on <dattaBaseName>.<tableName>
from <userName>@<hostName>

角色管理

角色是权限的集合,用户可以被赋予角色,同时也被赋予角色包含的权限。方便管理拥有相同权限的用户。

创建角色

create role <roleName>@<hostName>

给角色赋予权限

grant 
|<grantName> on <dattaBaseName>.<tableName>  #指定权限
|all privileges #所有权限
to <roleName>@<hostName>

查看角色的权限

show grants for <roleName>@<hostName>

撤销角色权限

revoke 
|<grantName> on <dattaBaseName>.<tableName>  #指定权限
|all privileges #所有权限
from <roleName>@<hostName>

删除角色

drop role <roleName>@<hostName>

给用户赋予角色

grant role <roleName>@<hostName> to user <userName>@<hostName>

撤销用户的角色

revoke role from <roleName>@<hostName>

激活权限

创建角色后默认情况下都是没有被激活的,只有手动激活用户擦能拥有角色对应的权限。

set default role all to <userName>@<hostName>

你可能感兴趣的:(数据库,mysql,sql,学习)