MySQL基础学习笔记(详细)

文章目录

    • MySQL连接
    • MySQL命令行编码问题
    • MySQL数据类型
      • 1、整数(xxxint)
      • 2、浮点小数
      • 3、定点小数
      • 4、日期时间类型
        • datetime和timestamp
      • 5、字符串类型
        • char和varchar区别
    • MySQL的运算符
    • MySQL导入导出
      • 数据库备份
      • 导入执行备份的sql脚本
    • SQL语句规范
      • 1、查看字符集和校对规则
      • 2、‘’
      • 3、别名
      • 4、要使用英文半角符号
      • 5、(),单引号,双引号成对结束
      • 6、注释
      • 7、命名规范
    • SQL的分类
      • SQL的三种类型
      • DDL(基本操作)
        • 数据库操作
        • 表操作
      • DML(基本操作)
        • 插入数据
        • 修改数据
        • 删除数据
        • 查询数据
    • 约束与索引
      • 关系数据库设计规则
      • 约束类型
      • 约束(CONSTRAINTS)与索引(INDEX)
      • MySQL不支持检查约束:check
      • 查询某个表的约束
      • 删除表的约束
      • 查询索引名
      • 删除索引名
      • 主键约束:primary key
        • 建表后如何指定主键约束
        • 主键约束分为两种:
        • 创建复合主键约束
        • 删除主键约束
      • 唯一键约束:
        • 创建、修改、删除唯一键
      • 非空约束
        • 创建、修改、删除非空约束
      • 默认值约束
        • 创建、修改、删除默认值约束
      • 自增约束
        • 创建、修改、删除自增约束
      • 外键约束
        • 约束的等级(5个):
        • 创建、修改、删除外键
    • 单行函数
      • 字符串函数
      • 数值函数
      • 日期时间函数
      • date_format,str_to_date格式
      • 流程函数
      • 其它函数
    • 组函数
    • 关联查询(联合查询)
      • 内连接:
      • 左连接:
      • 右连接:
      • 全外连接:
      • 自连接:
    • select语句6大子句
    • 子查询
        • 子查询分为三类:
    • 事务
      • 事务处理
      • 事务的ACID属性
      • 手动开启事务
      • 事务的隔离级别
      • 查询、修改当前隔离级别:
      • 事务回滚和提交的有效性
    • 用户与权限
      • 身份验证:
      • 分配权限
      • 查看用户权限
      • 忘记root用户密码(未测试,不支持mysql8版本)
      • MySQL8版本忘记密码(亲测有效)

MySQL连接

mysql -hlocalhost -P3306 -uroot -p

  1. 如果连接的是localhost本地的mysql,可以省略localhost
  2. 如果连接的MySQL服务的端口号是3306,可以省略-P3306
  3. -h,-P,-u这三个options后面可以有空格,eg:-h localhost,但是-p与密码之间不要加空格,否则会认为这个空格是密码的其中一个字符。

MySQL命令行编码问题

  1. 修改客户端的字符集编码为UTF-8
  2. set names gbk;告知mysql管理软件,客户端是gbk编码

MySQL数据类型

1、整数(xxxint)

整数类型 字节 最小值(有符号/无符号) 最大值(有符号/无符号)
TINYINT 1 -128/0 127/255
SMALLINT 2 -32768/0 32767/65535
MEDIUMINT 3 -8388608/0 8388607/1677215
INT、INTEGER 4 -2147483648/0 2147483647/4294967295
BIGINT 8 -9223372036854775808/0 9223372036854775807/18446744073709551615

int(11)表示一位的符号位,然后10位数字位。

int(M):M表示存储数值显示后的位数,M最大255,不是实际的存储的位数,

bigint(20)如果不是unsigned,表示一个符号位,19个数字位。

bigint(20)如果是unsigned,因为unsigned会扩大为原来最大值的2倍+1。此时少了一个符号位,但是数字位数多了一位。所以还是20。

想要表示宽度需要结合另外的两个参数使用

如果不加unsigned,直接加zerofill。默认自动添加unsigned。

  • unsigned:表示无符号
  • zerofill:表示用0填充

int(5) unsigned zerofill,表示每一个整数有5位数字,如果不足5位在左边用0填充。

如果只是单独的int(5),不会起作用。

无论int的宽度指定为多少,在内存中都是占4个字节,如果你的数字超过int(5)也可以存储

2、浮点小数

  • float:4个字节
  • double:8个字节

使用float和double时:

  1. float(M,D),double(M,D):M表示总位数,D表示精度,即小数点几位

例如:double(5,2)表示的数据范围:[-999.99 , 999.99],如果超过这个范围就会报错

3、定点小数

类似于Java的BigDecimal,底层用字符串存储

DECIMAL,DECIMAL(M,D)

4、日期时间类型

  • date:只能表示日期 YYYY-MM-DD 范围:1000-01-01到9999-12-31

  • time:表示时间 HH:MM:SS -838:59:59 到 838:59:59:

  • datetime:表示日期和时间 YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00 9999-12-31 23:59:59

  • year:表示年 YYYY YY(不推荐)1901-2155

  • timestamp:时间戳,表示日期和时间 YYYY-MM-DD

    HH:MM:SS 1970-01-01 00:00:01到2038-01019 03:14:07

datetime和timestamp

  1. timestamp实际存储的毫秒值,显示时,根据毫秒值算出本地化的日期时间。datetime就是存储日期时间。
  2. timestamp因为存储的毫秒值,所以在比较和计算时,效率较高。
  3. datetime和timestamp可以表示的时间范围不同。

5、字符串类型

MySQL没有但单字符类型,只有字符串类型。注意不是字节单位!一个字母是一个字符,一个汉字也是一个字符

  • char:定长字符串,长度[1,255];char,char(1),长度为1个字符;char(10),长度为10个字符
  • varchar:变长字符串;varchar(M):必须指定M,这个M的意思是最长不超过M
  • text:长文本;一般用于存储,文字比较多的,简介等,又不经常检索的。

char和varchar区别

char(M):M个字符就占M个字符的空间

varchar:实际几个字符+2个字节的空间,varchar(20),实际存储的是’张三‘,占的2个字符+1或2个字节(用来记录实际的长度)

varchar节省空间,但是每次存和取,都要数字符个数

char:看起来浪费空间,但是每次存和取,都按照固定的长度去处理。

建议:身份证号,学号,邮编等使用char

MySQL的运算符

类型
算术运算符 +、-、*、/(除也可以写成div,但是会取整,"/"会保留小数部分)%(mod)
比较运算符 = > >= < <= !=(<>) <=>(安全等于)
逻辑运算符 &&(and)||(or) not(逻辑非) xor(逻辑异或)
范围 between……and……(表达式>=…… and 表达式 <=……)
not between……and……(表达式<…… || 表达式 >……)
集合 in(值,值,值)
not in(值,值,值)
模糊查询 like 、not like
通配符:%表示0-n个字符,_表示1个字符
位运算符 &(按位与) |(按位或)^(按位异或)~(按位取反)>>(右移)<<(左移)
NULL值判断 is null、is not null
xxx is null可以使用xxx <=> null,xxx is not null可以使用not xxx <=> null

xor

#查询薪资大于1000 异或 性别是男的,即他俩只能满足一个。
#即薪资大于1000的女的 和薪资小于1000的男的
select * from t_employee where salary >1000 xor gender ='男'

MySQL导入导出

数据库备份

mysqldump -h主机地址 -P端口号 -uroot -p密码 --database 数据库名 > 文件路径/文件名.sql

导入执行备份的sql脚本

source sql脚本路径名.sql

SQL语句规范

  • MySQL对于sql语句不区分大小写,sql语句的关键字尽量大写。至于表中的数据是否区分大小写,和字符编码、数据类型、校对规则有关。

1、查看字符集和校对规则

对数据值是否区分大小写,和字符集和校对规则有关。

_ci(case ignore大小写不敏感),_cs(大小写敏感),_bin(二元,即比较是基于字符编码的值而与language无关,最严格,区分大小写,以二进制值存储)

命令:show character set;

2、‘’

在sql语句中的值,除了数值类型(整数,小数),其它类型,都用‘’引起来。

3、别名

如果在sql中需要给字段取别名,可以给别名加上 “ ”,如果别名中间没有空格可以省略。

select id as “编 号” from t_employee

如果给表名取别名,不能加“ ”。

4、要使用英文半角符号

5、(),单引号,双引号成对结束

6、注释

  • #单行注释
  • –空格单行注释
  • /**/多行注释

7、命名规范

  1. 数据库、表名不得超过30个字符,变量名限制为29个。
  2. 必须只能包含 A-Z,a-z,0-9,_,字母数字下划线共63个字符。
  3. 不能在对象名的字符间留空格
  4. 避免重名;同一个DB数据库中,表不能重名;同一个表中,字段不能重名;同一个DBMS数据库管理软件中,数据库不能重名。
  5. 命名时不要使用关键字。
  6. 保持字段名和类型的一致性。

SQL的分类

SQL的三种类型

  1. DDL:Data Define Language;数据定义语言,即定义数据的结构。例如:create,drop,alter
  2. DML:Data Manage Language;数据管理语言,对数据值的增删改查。例如:insert,delete,update,select。
  3. DCL:Data Control Language;数据控制语言,对权限、事务等的控制。例如:grant(授权),revoke(取回权限),commit,roolback等。

DDL(基本操作)

数据库操作

#数据库
show databases;

user 数据库名;

create database 数据库名;

drop database 数据库名;

表操作

#操作表
user 数据库名;show tables;

show tables from 数据库名;

create table [数据库名.]表名(
	字段1 数据类型,
   	字段2 数据类型,
	字段3 数据类型
)
#查看表结构 description描述简写
desc 表名称;

#修改表名称
rename table 旧表名 to 新表名;
alter table 旧表名 rename 新表明;

#修改表结构

#增加一列存储电话号码
alter table [数据库名.]表名称 add [column] 字段名 数据类型;#默认添加到最后
#增加到第一列
alter table [数据库名.]表名称 add [column] 字段名 数据类型 first;
#增加一列到指定字段名后
alter table [数据库名.]表名称 add [column] 字段名 数据类型 after 另一个字段名;

#修改字段名的 数据类型或位置
alter table [数据库名.]表名称 modify [column] 字段名 新的数据类型;
alter table [数据库名.]表名称 modify [column] 字段名 数据类型 first;
alter table [数据库名.]表名称 modify [column] 字段名 数据类型 after 另一个字段名;
#修改列的名称
alter table [数据库名.]表名称 change [column] 旧字段名 新的字段名 数据类型;

#删除一列
alter table [数据库名.]表名称 drop [column] 字段名;

#删除表
drop table [数据库名.]表名称;

DML(基本操作)

插入数据

insert into [数据库名.]表名称 values(值列表);
insert into [数据库名.]表名称(字段列表) values(值列表);
insert into [数据库名.]表名称(字段列表) values(值列表),(值列表),(值列表);

修改数据

#如果没有where修改所有
update [数据库名.]表名称 
set	字段名1 =,
	字段名1 =,
	字段名1 =[where 条件];

删除数据

#删除该表所有数据
delete from [数据库名.]表名称#一行一行的删数据
truncate [数据库名.]表名称 #删除整张表这个效率更高,但是不能回滚。
#底层是把表drop掉,然后新建了一张空表。

查询数据

select * from [数据库名.]表名称;

#取别名
select 字段名 as "别名" from [数据库名.]表名称;

约束与索引

关系数据库设计规则

  • 遵循ER模型和三范式
    • E entity 代表实体 对应数据库中的一张表
    • R relationship代表关系的意思
  • 三范式:1、列不能拆分;2、唯一标识;3、关系引用主键

约束类型

  • 键约束:主键约束、外键约束、唯一键约束
  • Not NULL约束:非空约束
  • Check约束:检查约束
  • Default约束:默认值约束
  • 自增约束

约束(CONSTRAINTS)与索引(INDEX)

约束是用来对数据业务规则和数据完整性进行实施、维护。约束的作用范围仅限在当前数据库,约束可以被当做数据库对象来处理,它们具有名称和关联模。是逻辑约束,不会因为设置约束而额外占用空间。

索引是一个单独、物理的存储在数据页上的数据库结构,它是表中一列或若干列值的集合和相应的指向表中数据值的物理标识数据页的逻辑指针清单。索引的存在会增加数据库的存储空间,也会使插入、修改数据的时间开销变多(因为插入和修改数据的时候,索引也要改变),但是可以大大提高查询速度。因此应该在键列、或其它经常要查询、排序、按范围查找的列上建立索引,而对于查询中很少使用和参考的列,修改频繁的列,值很少的列(例如:性别只有男和女)等列上不应该创建索引。

MySQL会再主键、唯一键、外键列上自动创建索引,其它列需要索引的话,需要手动创建。

其中主键删除,对应的索引也会删除。

删除唯一键的方式是通过删除对应的索引来实现的。

删除外键,外键列上的索引还在,如果需要删除,需要单独删除索引。

MySQL不支持检查约束:check

MySQL不支持;

#mysql虽然可以定义 但是没有效果
create table t_stu(
    id int primary key,
    name varchar(20),
    gender char check('男' or '女')
);

查询某个表的约束

select * from information_schema.table_constraints where table_name = '表名';
#或者
show create table 表名;

删除表的约束

alter table [数据库名.]表名 drop foreign key 约束名;

查询索引名

#查询索引名
show index from [数据库名.]表名;

删除索引名

drop index 索引名称(默认是字段名) on [数据库名.]表名;

主键约束:primary key

主键的特点:

  1. 唯一并且非空
  2. 一个表只能有一个主键约束
  3. 主键约束名就叫做PRIMARY
  4. 创建主键会自动创建对应的索引,同样删除主键也会删除对应的索引。

建表后如何指定主键约束

alter table [数据库名.]表名 add primary key(字段列表);

主键约束分为两种:

  1. 单列主键约束
  2. 复合主键约束

创建复合主键约束

create table [数据库名.]表名(
	字段1 数据类型,
   	字段2 数据类型,
	字段3 数据类型,
    primary key(字段列表)
)

删除主键约束

alter table [数据库名.]表名 drop primary key;

唯一键约束:

特点:

  1. 一个表可以有多个唯一键约束。
  2. 唯一键约束意味着,唯一,可以为NULL。
  3. 唯一键的约束名可以自己指定,也可以默认。
    1. 如果默认的话,一般如果单列唯一,默认就是列名。
    2. 如果是多列组合唯一,那么默认是该组合第一列的名称。
  4. 创建唯一键约束,约会在对应列上建立索引。而且删除唯一键约束的方式是通过删除对应索引来实现的。

创建、修改、删除唯一键

create table [数据库名.]表名(
	字段1 数据类型 ,
   	字段2 数据类型 ,# unique key只适用于单列的唯一键
	字段3 数据类型,
    primary key(字段列表),
    unique key(字段列表)    
);
alter table [数据库名.]表名 add unique key(字段列表);
alter table [数据库名.]表名 drop index 索引名;

非空约束

特点:

  1. 一个表可以有很多非空约束。
  2. 非空约束只能针对某一字段来说。
  3. 非空约束意味着,该字段不能存入NULL值。

创建、修改、删除非空约束

create table [数据库名.]表名(
	字段1 数据类型 ,
   	字段2 数据类型 not null,只适用于单列的唯一键
	字段3 数据类型,
    primary key(字段列表),
    unique key(字段列表)    
);
alter table [数据库名.]表名 modify 字段名 数据类型 not null;
alter table [数据库名.]表名 modify 字段名 数据类型;

默认值约束

特点:

  1. 一个表可以有很多的默认值约束。
  2. 默认值约束只能针对某一字段来说。
  3. 默认值约束意味着,该字段值为null,采取默认值。

创建、修改、删除默认值约束

create table [数据库名.]表名(
	字段1 数据类型 ,
   	字段2 数据类型 [unique key] [not null] default 默认值,
	字段3 数据类型 default 默认值,
    primary key(字段列表),
    unique key(字段列表)    
);
insert into [数据库名.]表名(,default,default);
insert into [数据库名.]表名(id)values();

alter table [数据库名.]表名 modify 字段名 数据类型 default 默认值 [not null];
alter table [数据库名.]表名 modify 字段名 数据类型;#default 和 not null 都会删除

自增约束

特点:

  1. 一个表只能有一个自增约束。因为一个表只能有一个维护自增值的变量。

  2. 自增约束的列必须是整数列。

  3. 自增约束的列必须是键列(主键,唯一键,外键)。实际中主键最多。

  4. 自增列如何自增

    1. 如果指定值(如果不是unsigned 可以是负数),就按照指定的来,没有指定就自增。

    2. 如果指定的值为0或null,按照自增的来。

    3. 如果中间有空余的比方说1 2 3 7 8中间没有4 5 6。插入一次4后下次不指定值以最大的8自增。

创建、修改、删除自增约束

create table [数据库名.]表名(
	字段1 xxInt primary key auto_increment,
   	字段2 数据类型 ,
	字段3 数据类型 default 默认值,
);
alter table [数据库名.]表名 modify 字段名 xxxint auto_increment;
alter table [数据库名.]表名 modify 字段名 数据类型;

外键约束

特点:

  1. 一个表可以有多个外键约束。
  2. 外键约束是需要一个表的两个字段或两个表的两个字段之间建立外键约束。
  3. 外键约束一定时在从表/子表中建立的。
  4. 在从表中外键约束列,与主表中外键约束参考的列,这两个列的名称可以不一同,但是意义,数据类型必须一致。
  5. 外键约束是约束双方的。
    1. 对于主表来说:修改和删除受约束了,
    2. 对于从表来说:添加和修改就受约束了,只能选主表中存在的数据。
  6. 主表中被依赖的字段/列必须是键列

建表先建主表,再键从表;

删表先删从表,再删主表;

从表、子表:参考别人的,依赖别人的。

主表、父表:被参考的,被依赖的。

举例:
1、部门表和员工表。员工表中有一个字段,表示该员工所在的部门。
	部门表是主表
	员工表是从表,说员工选择进入哪个部门。
	外键建立在员工表中
2、学生,课程,选课表
	学生,课程是主表
	选课表是从表

约束的等级(5个):

  1. Cascade方式:级联。主动权在主表上,如果主表被依赖字段修改、删除了,从表对应的字段的记录跟着修改、删除。
  2. Set null方式:主动权在主表上。
    1. 如果主表被依赖字段修改了,从表对应的外键字段设置为null;
    2. 如果主表被依赖字段的记录删除了,从表对应的外键字段的值设置为null;
    3. 这里要求,外键字段必须不能有非空约束。
  3. No action方式:不作为。
  4. Restrict方式:严格。
    1. (系统默认的方式)在3、4中主表失去了主动权,如果主表的被依赖字段的值被引用了,那么主表对该字段的修改和删除就被完全限制了,就不能修改和删除。
    2. 主表没有主动权,必须先处理从表对应的值,然后才能修改和删除。
  5. Set default方式:子表外键将设定成一个默认的值,MySQL的Innodb引擎不支持。

创建、修改、删除外键

删除外键后,索引还会存在。

create table [数据库名.]表名(
	字段1 xxInt primary key auto_increment,
   	字段2 数据类型 ,
	字段3 数据类型 default 默认值,
    。。。,
    [constraint 外键约束名] foreign key(从表的某字段) references 主表名(被参考的字段) [on update 等级] [on delete 等级]
    #外键约束名可以是 从表名_主表名_字段名_fk
);
#修改
alter table [数据库名.]表名 add [constraint 外键约束名] foreign key(从表的某字段) references 主表名(主表被引用字段) [on update 等级] [on delete 等级];
#删除先查看外键约束名
select * from information_schema.table_constraints where table_name = '表名';
alter table [数据库名.]表名 drop foreign key 约束名;

单行函数

  • 只对一行进行变换,每行返回一个结果
  • 可以嵌套
  • 参数可以是一个字段或一个表达式或一个值

字符串函数

函数 用法
concat(s1,s2,…) 连接s1,s2,s3…为一个字符串
concat_ws(s,s1,s2,s3,…) 同concat函数,但是以s作为连接符。
char_length(s) 返回字符串的s的字符数
length(s) 返回字符串s的字节数,和字符集有关
insert(str,index,len,instr) 将字符串str从第index位置开始,len个字符长的子串替换为字符串instr
upper(s)或ucase(s) 所有字母转化成大写字母
lower(s)或lcase(s) 所有字母转化为小写字母
left(s,n) 返回字符串最左边n个字符
right(s,n) 返回字符串最右边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([both] s1 from s) 去掉字符串s开始与结尾的s1
trim([leading] s1 from s) 去掉字符串s开始处的s1
trim([trailing] s1 from s) 去掉字符串s结尾处的s1
repeat(s,n) 返回字符串s重复n次的结果
replace(str,a,b) 用字符串b替换字符串str中所有出现的字符串a
strcmp(s1,s2) 比较字符串s1,s2
substring(s,index,len) 返回从字符串s的index位置起len个字符,index不是下标,是第几个字符。

数值函数

函数 用法
abs(x) 返回x的绝对值
ceil(x) 返回大于x的最小整数值
floor(x) 返回小于x的最大整数值
mod(x,y) 返回x/y的模
rand() 返回0到1之间的随机值。
round(x,y) 返回参数x的四舍五入,有
truncate(x,y) x截断y位小数,多的直接舍去,少的填0。
pow(x,y) x的y次方
sqrt(x) 返回x的平方根

日期时间函数

函数 用法
now(), sysdate(), current_timestamp(),
localtime(), localtimestamp()
当前系统时间yyyy-MM-dd HH:mm:ss
curdate(), current_date() 只有日期
curtime(), current_time() 只有时间
year(date), month(date), day(date),
hour(time), minute(time), seconde(time)
yyyy-MM-dd HH:mm:ss
week(date), weekofyear(date) 一年中的第几周
dayofweek(date) 返回周几,周日是1,周一是2,周六是7
weekday(date) 返回周几,周一是0,周二是1,周日是6
dayname(date) 返回星期,MONDAY,TUESDAY…SUNDAY
monthname(date) 返回月份January,February,March…
datediff(date1,date2)/timediff(time1,time2) 返回date1-date2的时间间隔(多少天)/返回time1-time2的时间间隔(HH:mm:ss,最大838:59:59)
date_add(datetime,INTERVAL expr type) 返回与给定日期时间增加exper(数值,可以为负数),type(类型)时间的日期。eg:date_add(now(),interval 3 year);增加3年
date_format(datetime,fmt) 按照字符串fmt格式化日期datetime值
str_to_date(str,fmt) 将字符串按照fmt格式化为日期

date_format,str_to_date格式

'%Y-%m-%d %H:%i:%s' #是这样的格式2019-3-24 13:02:01
格式符 说明
%Y 表示4位数字表示年份
%y 表示两位数字表示年份
%M 月名表示月份(January,…)
%m 两位数字表示月份(01,02,…)
%b 缩写的月份名(Jan,Feb,…)
%c 表示月份(1,2,3)
%D 英文后缀表示月中的天数(1st,2nd,3rd)
%d 两位数字表示月中的天数(01,02,…)
%e 数字形式表示月中天数(1,2,3,…)
%H 两位数字表示小时,24小时制(01,02,…)
%h和%I(大写的i) 两位数字表示小时,12小时制(01,02,…)
%k 数字形式的小时,24小时制(1,2,3)
%l(小写的L) 数字形式的小时,12小时制(1,2,3)
%i 两位数字表示分钟(00,01,02)
%S,%s 两位数字表示秒(00,01,02)
%W 一周中的星期名称(Monday,Tuesday,…)
%a 一周中的星期名称缩写(Mon,Tue,…)
%w 以数字表示周中的天数,(0=Sunday,1=Monday)

流程函数

函数 用法
if(value, t, f) 如果value是真,返回t,否则返回f
ifnull(value1, value2) 如果value1不为NULL,返回value1,否则返回value2.
CASE
WHEN 条件1 THEN result1
WHEN 条件2 THEN result2…
[ELSE resultn]
END
相当于java的if… else if… else… 。
CASE expr
WHEN 常量值1 THEN result1
WHEN 常量值2 THEN result2…
[ELSE resultn]
END
相当于java中的switch(expr) case

其它函数

函数 用法
database() 返回当前数据库名
version() 返回当前数据库版本
user() 返回当前登录用户名
password(str) 返回字符串str的加密版本,41位长的字符串。(mysql8中移出了该函数)
md5(str) 返回字符串的md5值,也是加密

组函数

  • AVG()
  • SUM()
  • MAX()
  • MIN()
  • COUNT()
    • count(*)和count(1)谁好?
      • 对于myisam引擎没有区别。这种引擎内部有一计数器在维护行数。
      • 对于Innodb引擎的表用count(*),效率很低,因为innodb,真的要去读行数。

关联查询(联合查询)

  1. A∩B
  2. A
  3. A-A∩B
  4. B
  5. B-A∩B
  6. A∪B
  7. A∪B-A∩B

如何实现这些结果

  1. 内连接:inner join
    • A∩B
  2. 外连接
    1. 左外连接:left join
      • A
      • A-A∩B
    2. 右外连接:right join
      • B
      • B-A∩B
    3. 全外连接:full join。MySQL不支持全外连接,但是可以使用union(合并)结果来实现
      • A∪B :A union B
      • A∪B-A∩B :A - A∩B union B-A∩B

内连接:

如果少了关联条件会出现笛卡尔积,(全排列)

select 字段列表
from A表名 inner join B表名
on 1个关联条件
where 其他条件等

select 字段列表
from A表名 inner join B表名 inner join C表名
on 2个关联条件
where 其他条件

select 字段列表
from A表名 , B表名 , C表名
where 2个关联条件 and 其他条件

左连接:

  1. A :其中A表中所有列都会显示(即使,该关联的字段为null,另一个表中没有)

    select 字段列表
    from A表名 left join B表名
    on 关联条件
    where 其他条件等
    
  2. A-A∩B:只会显示没有关联的列(即关联字段为null)

    select 字段列表
    from A表名 left join B表名
    on 关联条件
    where 关联字段(从表) is null and 其他条件等
    

右连接:

和左连接对应,正好相反。

全外连接:

  1. A∪B:A union B

    select 字段列表
    from A表名 left join B表名
    on 关联条件
    where 其他条件等
    
    UNION
    
    select 字段列表
    from A表名 right join B表名
    on 关联条件
    where 其他条件等
    
  2. A∪B - A ∩ B :A - A ∩ B union B - A ∩ B

    select 字段列表
    from A表名 left join B表名
    on 关联条件
    where 关联字段(从表) is null and 其他条件等
    
    UNION
    
    select 字段列表
    from A表名 right join B表名
    on 关联条件
    where 关联字段(从表) is null and 其他条件等
    

自连接:

一种特殊的联合查询,因为现在联合查询的两种表本质是一个表。通过取别名,模拟两张表

select 字段列表
from 表名 别名1 inner/left/right join 表名 别名2
on 别名1.关联字段 = 别名2.关联字段
where 其他条件

select语句6大子句

  1. from子句:后面跟表,视图,多行多列的二维表结构。
  2. where子句:后面跟条件,用于原表的记录中。不能跟分组函数。
  3. group by子句:后面跟字段列表。意思是分组。例如有1、2、3班。查询每个班的总人数。
    • 分组查询的结果字段中,不要出现与分组无关的字段。一般是group by后面的字段列表,分组函数
  4. having子句:后面跟条件。意思是对分组后的结果,再加条件。例如有1、2、3班。查询每个班的总人数,一 个班人数大于10的班。
    • 可以跟分组函数。可以是对原表的筛选,更多的用于分组后的结果。
  5. order by子句:后面跟字段或表达式(字段 desc/asc)。意思是排序。
    • desc(descending)降序
    • asc(ascending)升序,可省略
  6. limit子句:取几条记录。limit m,n。m表示从第几条记录(第一条从0开始)开始取,n表示最多取n条。通常用于分页查询。
    • page代表第几页,pageSize代表每页的数量。 limit (page-1)*num ,pageSize;

PS:书写顺序是1-6;

子查询

在一个查询中嵌套了另一个查询,那么这个嵌套在里面的查询称为子查询。子查询的结果作为外部查询的条件或者数据的筛选范围来使用。

子查询分为三类:

  1. where型:子查询的结果作为外部查询的条件使用的。

    • 子查询结果是:单值的结果,比较运算符。
    • 子查询结果是:一列多行的结果(多值)。in(),比较运算符 all(),比较运算符 any()。
    #比这几个人都高的薪资
    select *
    from t_employee
    where salary > ALL(xxx,xxx,xx)
    
    #查找这几个人的薪资
    select *
    from t_employee
    where name in(xxx,xxx,xx)
    
    select *
    from t_employee
    where name = ANY(xxx,xxx,xx)
    
    
  2. from型:子查询的结果是作为外部查询的筛选范围来使用的。

    #对子查询的多行多列的二维表结构的临时表取别名。给分组函数取别名。
    select 部门.id , 部门.name, temp.countOfDep
    from 部门 inner join (select id,count(*) as countOfDep from 部门 group by id) temp
    on 部门.id = temp.id
    
  3. exists型:子查询的结果是作为外部查询的条件使用的。

    #查询部门信息,要求这些部门必须有员工
    select * from 部门
    where exists(
    	select * from 员工
        where 部门.id =员工.部门id
    )
    #将部门中的信息带入子查询去匹配,如果能查询出记录就保留,否则去掉
    

事务

事务处理

事务处理:保证所有事物都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有操作都被提交(commit),修改永久保存下来了;要么数据库管理系统将放弃所有的修改,整个事务回滚(rollback)到最初状态。

事务的ACID属性

  1. 原子性(Atomicity):原子性是指事务是一个不可分割的单位,事务中的操作要么都发生,要么都不发生。
  2. 一致性(Consistency):事务必须使数据库从一个一致性状态变换成另一个一致性状态。
  3. 隔离性(Isolation):事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作以及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能相互干扰。
  4. 持久性(Durability):持久性是指一个事务一旦被提交,它对数据库的数据的改变是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。

手动开启事务

方式一

set autoCommit=false;

…都是需要手动提交的。

set autoCommit=true;

方式二

start transaction;

一个事务

commit;或rollback;

事务的隔离级别

同一个库的同一个表同一个记录,对于多个事务来说,就是共享数据。多个事务被多个线程同时执行时,那么共享数据就会线程安全问题。

  1. read uncommitted:读未提交数据。允许事务读取未被其他事务提交的变更。脏读,不可重复读和幻读的问题都会出现。
    • 事务1,可以读取到事务2已经修改,但是还没正式提交的数据。
  2. read committed:读已提交的数据。只允许事务读取已经被其他事务提交的变更。可以避免脏读,但不可重复读和幻读问题仍然可能出现。
  3. repeatable read:可重复读。确保事务可以多次从一个字段中读取相同的值,在这个事务持续时间,禁止其他事务对这个字段进行更新。可以避免脏读和不可重复读,但幻读的问题仍然存在。注意:MySQL,innodb使用了MVCC(Multiversion Concurrency Control),即多版本并发控制技术防止幻读。真正的像拍照一样,其他事务新插入或删除的记录也看不出来。
  4. serializable:串行化。确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作,所有的并发问题都可以避免,但性能十分低。

几种问题:

  1. 脏读现象:事务1对某个记录进行修改,还未提交。事务2就看到了。那么这个被事务1修改还未提交的数据就是脏数据。

  2. 不可重复的:事务1对某个表进行修改,已经提交。但是事务2在事务1提交之前,查询了这个记录,在事务1提交后,又查询了这个记录,对于事务2出现了不可重复读的现象。在同一个事务中,前后两次对同一个记录的读取结果不一样。

  3. 幻读:事务1给某个表添加了新的记录,或者删除了某个记录。记录数有变化。并且提交了。

    ​ 事务2,在事务1提交之前,查询了这个表,在事务1提交之后,查询了这个表。

    ​ 对于事务2来说前后两次的记录数不一样。

    ​ 但是MySQL在升级了隔离级别3,也可以避免幻读。

查询、修改当前隔离级别:

-- mysql 5版本
select @@tx_isolation;
set tx_isolation = 'read-uncommitted';

-- mysql 8版本 改名了
select @@transaction_isolation;
set transaction_isolation = '';

事务回滚和提交的有效性

事务回滚和提交只对insert、update、delete有效。

对create、drop等DDL语句无效。

用户与权限

身份验证:

  1. ip+用户名作为身份验证
    • root@localhost:只允许在本机使用root用户登录
    • root@%:运行在任意机器上使用root用户登录
    • [email protected]:只运行在该ip地址的主机上使用root用户登录
    • rhythm@%:运行在任意机器上使用rhythm用户登录。

分配权限

  1. 全局
  2. 数据库
  3. 字段

如果前面的通过了,后面就不校验了。

查看用户权限

show grants for user@host
user:用户名 (root)
host:主机ip (localhost)

忘记root用户密码(未测试,不支持mysql8版本)

  1. 关掉mysqld(服务进程)
  2. 通过命令行+特殊参数开启mysqld
    • mysqld --skip-grant-tables
  3. 此时,mysqld服务进程已经打开,而且不需要权限检查。(可能需要再打开一个命令行,不要关闭当前这个)
  4. mysql -uroot直接登录
  5. 修改权限表
    • use mysql;
    • update user set Password = password(‘123456’) where User = ‘root’;
    • flush privileges;
  6. 关掉mysqld服务
  7. 通过服务管理打开mysqld服务
  8. 再次登录即可。

MySQL8版本忘记密码(亲测有效)

注意:要用管理员权限打开cmd命令行。

  1. 停止你的mysql服务

    一般使用net stop mysql(如果你没有修改过服务名默认mysql)

  2. 在随便一个地方新建一个txt文档,名字随意。

    比如我在c盘output目录下新建了个reset.txt,输入以下内容,设置密码为123456(修改成你的)。

    alter user 'root'@'localhost' identified by '123456';
    
  3. 在命令行中输入以下内容,文件路径是你的txt文档路径,显示几行东西后后关闭窗口即可。

    mysqld --init-file=c:\output\reset.txt --console
    
  4. 重新启动mysql服务,用你的新密码登录即可。

    net start mysql

如果你没有忘记密码,只是想修改密码。

直接登录进去,然后使用该命令即可修改密码

alter user 'root'@'localhost' identified by '123456';

你可能感兴趣的:(MySQL基础学习笔记(详细))