MySQL学习笔记-基础介绍

2023-12-08 10:37:04 浏览数 (1)

1、使用终端登录mysql

1)在终端输入命令:

PATH=“$PATH”:/usr/local/mysql/bin

2)输入:

mysql -u root -p

3)输入密码

4)输入show databases;

2、数据库的操作

1)创建数据库

create database Students;

2)查看所有数据库

show databases;

3)选择数据库

use Students;

4)删除数据库

drop database Students;

3、表的操作

3.1、创建表

代码语言:txt复制
语法格式:

use 数据库名称;
create table table_name(
	属性名 数据类型 属性约束,
	......
)

或者

create table 数据库名称.table_name(
	属性名 数据类型 属性约束,
	......
)

use Students;
//学生表
create table Student(
	Sno int primary key auto_increment,
	Sname varchar(10) not null,
	Ssex varchar(2) check(Ssex='男' or Ssex='女'),
	Sage int check(Sage between 15 and 45),
	Sdept varchar(20) default('计算机系'),
	//Sroomid int unique,
	Sroomid int,
	//如果想给字段:Sroomid上的UK约束设置一个名字,可执行constraint语句
	constraint uk_Sroomid unique(Sroomid)
);

//课程表
Create table Cource(
	Cno varchar(10) primary key,
	Cname varchar(20) not null,
	Ccredit int check(Ccredit>0),//学分
	Semester int check(Semester>0),//学期
	Period int check(Period>0)//学时
)
//学生选课表
create table StudentCourse(
	sno varchar(7),
    	foreign key(sno) references Student(sno),
	cno varchar(10),
    	foreign key(cno) references Cource(cno),
	grade int,check(grade between 0 and 100),
	primary key (sno,cno)
)

3.2、查看表结构

语法:Describe 表名;

可简写为:desc 表名;

3.3、查看表详细定义

show create table 表名;

3.4、删除表

drop table 表名;

3.5、修改表

代码语言:txt复制
 3.5.1、修改表名
alter table old_table_name rename new_table_name;

3.5.2、增加字段
alter table table_name add 属性名 属性类型;

//在表的第一个位置增加字段
alter table table_name add 属性名 属性类型 first;
//在表的指定字段后增加字段
alter table table_name add 属性名 属性类型 after 属性名;

3.5.3、删除字段
alter table table_name drop 属性名;

3.5.4、修改字段(修改数据类型、字段名)
//修改字段的数据类型
alter table table_name modify 属性名 新数据类型;
//修改字段名
alter table table_name change 旧属性名 新属性名 旧数据类型;
//同时修改字段名和数据类型
alter table table_name change 旧属性名 新属性名 新数据类型;
//修改字段顺序
alter tabel table_name modify 属性名1 数据类型 first/afler 属性名2;

3.6、操作表的约束性

代码语言:txt复制
not null (约束的值不能为空)
default (设置字段的默认值)
unique key(uk) (约束字段的值唯一,不允许重复)
primary key(pk) (约束字段为表的主键,可作为该表记录的唯一标识)
auto_increment (约束字段的值自动增加)
Foreign key(fk) (约束字段的值为表的外键)

//设置主键
//如果想给Sno字段上的PK约束设置名字,可以执行constraint语句
Constraint pk_Sno prinmary key(Sno)

//多主键的情况给PK约束设置名字
Constraint pk_Sno_Sname prinmary key(Sno,Sname)

//自增列必须是primary key
alter table address address_id int primary key auto_increment;

//设置外键
语法格式:
create table table_name(
	属性名 数据类型
	constraint 外键约束名 foreign key(属性名1) references 父表名(主键-属性名2) 
)

4、MySQL数据库中存储引擎和数据类型

4.1、查看当前版本mysql所支持的存储引擎(默认支持innoDB)

show engines;

show engines like 'have%';

支持:CSV、ARCHIVE、BLACKHOLE、MRG_MYISAM、MYISAM、PERFORMANCE_SCHEMA、InnoDB、MEMORY

4.2、操作默认存储引擎

代码语言:txt复制
1、查询默认存储引擎
show variables like 'default_storage_engine%';
2、修改默认存储引擎
通过mysqlworkbench或者修改数据库管理系统的配置文件/etc/my.cnf

4.3、怎么选择存储引擎

代码语言:txt复制
MyISAM:由于该存储引擎不支持事务、也不支持外键,所以访问速度比较快。因此对事务完整性没有要求并以访问为主的应用适合此引擎。
InnoDB:由于该引擎在事务上具有优势,即支持具有提交、回滚和崩溃恢复能力的事务安装,所以比MyISAM占用更多的磁盘空间。因此需要进行频繁的更新、删除操作,同时还对事务的完整性要求比较高,需要实现并发控制,此时适合该引擎。
MEMORY:该引擎使用内存来存储数据,因此数据访问速度快,但是没有安全上的保障(若数据库发送崩溃或重启,表中数据会消失),需要进行快速访问,则适合该引擎。

4.4、数据类型

代码语言:txt复制
整形:tinyint、smallint、mediumint、int和integer、bigint
浮点型:float、double
日期和时间:date(年月日)、datetime(年月日时分秒)、timestamp(时间戳)、time(时分秒)、year(年份)
字符串:char(少量字符)、varchar(字符长度经常变换)
text:tinytext、text、mediumtext、longtext
binary: binary、varbinary
blob:tinyblob、blob、mediumblob、longblob

区别:
1、char和binary非常类似,但是前者只能存储字符数据,后者可以储存少量二进制数据(比如图片、音乐、视频文件等)
2、char和text非常类似,但是前者只能存储字符数据,后者可以储存大量二进制数据(比如图片、音乐、视频文件等)

5、数据维护

数据更新操作包括对数据的插入、修改、删除。

5.1 插入数据

5.1.1 插入单行数据
代码语言:txt复制
insert 语句格式:
//其中的1,2,...n分别对应表中的列,表中定义了几列,insert语句就应该对应几个值,数据类型得一致
insert into 表名 values (值1,值2,...值n);

insert into Students.Student values
	(null,'胡慧','女',18,'会计',302);

//查询插入结果	
select * from Students.student;
5.1.2 插入多行数据
代码语言:txt复制
insert into Students.Student values
	(null,'胡慧','女',18,'会计',302),
    (null,'胡集','男',19,'英语',209),
    (null,'何及','女',17,'机材',509)
5.1.3 基于外部表插入数据

insert 语句表示向指定表中添加新的数据,而 insert select 语句可以将某个外部表中的数据插入到另一个新表中。

代码语言:txt复制
语法格式:
//‘表名1’表示将获取到的记录查到哪个表中,‘表名2’表示从哪个表中查询记录
//‘列名列表1’表示为哪些列赋值,不设置表示所有列,‘列名列表2’表示从表中查询到哪些列的数据
insert into 表名1 (列名列表1) select 列名列表2 from 表名2 where 条件表达式

5.2 更新数据

5.2.1 update语句介绍
代码语言:txt复制
语法格式:
update table_name set column1=value1,[column2=value2]...
	where 条件表达式

1、如果不使用where语句,则表示修改整个表中的数据 2、where需要指定需更新的行,set子句指定新值 3、每次只能修改一个表中的数据 4、可以同时把一列或多列、一个变量或多个变量放在一个表达式总

5.2.2 更新单列

MySQL有个安全模式,安全模式下必须通过主键才能update操作

代码语言:txt复制
解除安全模式:set sql_safe_updates=0;
恢复安全模式:set sql_safe_updates=1;
代码语言:txt复制
-- 在安全模式下,where 子句中column必须是主键才能update操作
update Students.Student set Sdept='材料工程' where Sno=2;

-- 解除安全模式
set sql_safe_updates=0;

-- 非安全模式下update
-- update Students.Student set Sdept='飞行器设计' where Sname='何及';
5.2.3 更新多列
代码语言:txt复制
// 多列之间用逗号隔开
update Students.Student set Sdept='飞行器设计',Sroomid=309 where Sname='何及';
5.2.4 基于其他表更新列
代码语言:txt复制
update actor set last_update = '2023-8-01' where actor_id in
	(select actor_id from film_actor where film_id=1);
	
注意:
1、在一个单独的update语句中,MySQL不会对同一行做两次更新。
这是一个内置限制,可以使在更新中写入日志的数量减至最小。

2、使用 set 关键字 可以引入列的列表或各种要更新的变量名。其中 set关键字
引用的列必须明确。

3、如果子查询没有返回值,必须在子查询中引入 in、exists、any、all等关键字。 

5.3 删除数据

5.3.1 delete语句介绍及使用
代码语言:txt复制
语句格式:
delete table_or_view from table_sources where 条件语句;

1、table_or_view:是从中删除数据的表或视图的名称
2、FROM:table_sources子句为需要删除数据的表名称。它使 delete可以先从其他表查询出一个结果集,然后删除 table_sources中与该查询结果相关的数据

//删除单行数据
delete from actor where actor_id=204;
//删除多行数据
delete from actor where actor_id>200;
//删除表中所有数据
delete from actor;

1、在delete语句中没有指定列名,这是由于delete语句不能从表中删除单个列的值。它只能删除行。如果要删除特定列的值,可使用update把该列的值都设为null,当然该列必须支持null值。 2、delete语句只能从表中删除数据,不能删除表本身,要删除表的定义,可使用 drop table语句。 3、若delete语句中没有where子句,表中所有数据都将全部被删除 4、同insert和update语句一样,从一个表中删除记录将会引起其他表的参照完整性问题。这是一个潜在的问题,需时刻注意。

5.3.2 清空表数据

对于表已经过期或错误的数据可使用 truncate 关键字进行删除,也可使用delete语句。

代码语言:txt复制
语法如下:
truncate table table_name;

对于innoDB表,如果有需要引用表的外键限制,则truncate table 被映射到delete上;否则使用快速删减(取消和重新创建表)。使用truncate 重新设置 auto_increment计数器,设置时不考虑是否有外键限制。

对于其他存储引擎,MySQL中truncate table 和 delete from有以下区别。

(1)删除操作会取消并重新创建表,这比一行行地删除要快得多。

(2)删除操作不能保证事务是安全的,在进行事务处理和表锁定的过程中尝试进行删除,会发生错误。

(3)被删除行的数量没有被返回。

(4)只要表定义文件tbl_name.frm是合法的,则可以是truncate table 把表重新创建一个空表,即使数据或索引文件已经被破坏。

(5)表管理程序不记录最后被使用的 auto_increment值,但是会从头开始计数。即使对应MyISAM 和 innoDB 也是如此。MyISAM 和 innoDB 通常不再次使用序列值。

(6)当被用于带分区的表时,truncate table 会保留分区;即数据和索引文件被取消并重新创建,同时分区定义(.par)文件不受影响。

6、数据查询

6.1、select语句的语法

select语句从表中查询数据的基本语法如下:

代码语言:txt复制
select [all | distinct] select_list from table_or_view_name
[where <查找条件>]
[group by <分组条件>]
[having <查询条件>]
[order by <排序方式>] [asc | desc]

括号[]的内容是可选的

上述语法的说明如下:

(1)select 子句:用来指定查询返回的列。

(2)all | distinct:用来标识在查询结果集中对相同行的处理方式。all 表示返回查询结果集所有的行,其中包括重复行;distinct 表示如果结果集中有重复行,只返回一行,默认值是all。

(3)select_list:表示要查询的字段列名。如果返回多列,各列间用‘,’隔开;如果需要返回所有列的数据,则可以用'*'表示。

(4)from子句:用来指定要查询的表名或视图名。

(5)where子句:用来指定限定返回行的搜索条件。

(6)group by子句:用来指定要查询结果的分组条件。

(7)having子句:与group by 子句组合使用,用来对分组的结果进一步限定搜索条件。

(8)order by子句:用来指定结果集的排序方式。

(9)asc | desc:指定排序方式。升序(默认值)| 降序。

在select语句中from、where、group by 、order by 必须按照语法中列出的顺序依次执行,如果顺序不对就会出现语法错误。

6.2、简单查询

6.2.1 获取所有列
代码语言:txt复制
语法格式:
select * from table_name;

select * from Students.Student;
6.2.2 获取指定列
代码语言:txt复制
语法格式:
select 列名列表 from table_name;

select Sno,Sage,Sdept from Students.Student;
6.2.3 为列指定别名

当表或者列名的名称比较长时,使用别名很有用。在select语句查询中,可以使用两种方式为列指定别名。

(1)、采用符合 ANSI 规则的方法指定别名

代码语言:txt复制
select Sno '学号',Sage '年龄',Sdept '学院' from Students.Student;

(2)、使用 AS 关键字指定别名

代码语言:txt复制
select Sno as '学号',Sage as '年龄',Sdept as '学院' from Students.Student;
  • 为列操作别名操作时,必须注意以下几点:

(1)当引用中文别名时,可以不加引号,但是不能使用全角引号,否则会查询会出错。 (2)当引用英文的别名超过两个单词时,则必须用引号将其引起来。 (3)可以同时使用以上两种方法,会返回同样的结果集。

6.2.4 获取不重复的数据
代码语言:txt复制
select distinct * from Students.Student;
6.2.5 限制查询结果

(1)limit 指定初始位置

代码语言:txt复制
语法格式:limit 初始位置,查询记录数量;
//查询表中5条记录,指定从第 3条 记录开始显示
select * from Students.Student limit 2,5;

(2)limit不指定初始位置

代码语言:txt复制
语法格式:limit 显示记录数;
//查询表前 2条 记录
select * from Students.Student limit 2;
6.2.6 where 条件查询

where 设置查询条件时,where子句可以使用算术运算符(如 、-、*、/、%),比较运算符(如>=、<=、between 1 and 3、like)和逻辑运算符(如and、or、not)等多种运算符。

代码语言:txt复制
select * from Students.Student where Sno=2;

//查询Saddress的值以 江西 开头,以 ... 结尾的全部记录
// '%'表示任意长度的字符串,'_'只能表示单字符
select * from Students.Student where Saddress like '江西%...';
6.2.7 分组查询
代码语言:txt复制
语法格式:
group by 字段名 [having 条件表达式] [with rollup]

select * from Students.Student group by Sroomid;

//使用聚合函数 count(),计算Sroomid相同的有多少列
select *,count(Sroomid) from Students.Student group by Sroomid;

//使用聚合函数 group_concat(),查询每个寝室里住了哪些学生
select Sroomid,group_concat(Sno) from Students.Student group by Sroomid;

//对Sroomid分组查询,使用having筛选Sno>2的记录
select * from Students.Student group by Sroomid having Sno>2;

//使用where筛选Sno>2的记录,然后对Sroomid分组
select * from Students.Student where Sno>2 group by Sroomid;

上述语法的说明如下:

(1)字段名:它是按照该字段的值进行分组,指定多个字段时中间使用逗号(,)进行分隔

(2)having表达式:可选参数,用来限制分组后的显示,满足条件表达式的结果会被显示出来。

(3)with rollup:可选参数,将会在所有记录的最后加上一条,该记录是上面所有记录的总和。

(4)group by 可以单独使用,单独使用时查询结果就是字段取值的分组情况,字段中取值相同的记录为一组,但是只显示该组的第一条记录。

group by 子句后可跟多个分组字段列,多列间用逗号分隔。另外,MySQL 提供了一个聚合函数: group_concat,该函数会把每个分组中指定的字段值都显示出来。用于将多行合并成一行,返回一个由多个值组成的字符串。 //(column1, column2)存在一对多的关系 语法格式:SELECT column1, group_concat(column2) FROM table GROUP BY column1;

错误分组查询case:

代码语言:txt复制
//报错:this is incompatible with sql_mode=only_full_group_by,这是由于MySQL触发了sql_mode的only_full_group_by条件
//该条件要求:当对一个或多个字段进行分组后,所查询的字段(即select后跟的字段名),必须是分组所依据的字段和经过聚合函数聚合后的新字段。这个逻辑是合理的之所以要分组就是要探究该组内的信息,既然是组内信息,就必须对全组数据进行统一处理,单独拎某一个数据是不合理的。

//报错
select * from Students.Student group by Sroomid;

//所查询的字段和分组所依据的字段一致,正常查询
select Sroomid from Students.Student group by Sroomid;

//使用聚合函数max(),正常查询
//聚合函数包括max、min、avg、sum、count等
select max(Sno),Sroomid from Students.Student group by Sroomid;

解决办法:
1、从sql_mode端解决问题。
(1) 临时关闭only_full_group_by模式,这种方法通过修改系统变量,重启数据库后失效。

首先查看下当前的sql_mode:

show VARIABLES LIKE 'sql_mode';

//修改后需在新的回话里验证原SQL
set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

(2)永久关闭only_full_group_by模式,这种方法需要在mysql的配置文件里修改,然后重启。

Step 1 找到配置文件/etc/my.cnf(或则关联文件夹找到mysql-server.cnf)

Step 2: 在上述文件内的[mysqld]后追加(sudo vim /etc/my.cnf)

sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'

Step 3:保存配置文件后,重启Mysql即可。

group by 之后可以跟having 子句,它实现对结果集的筛选。使用having 语句查询和where 关键字类似,在关键字后插入条件表达式来规范查询结果。having 语句 和 where 的不同点有三个方面:

(1)having 针对结果组;where针对的是列的数据。

(2)having 可以和聚合函数一起使用;where 不能。

(3)having 只过滤分组之后的数据;where在分组前对数据进行过滤。。

6.2.8 对查询结果排序
代码语言:txt复制
语法格式:
//order_expression 表示排序列或列的别名和表达式
order by order_expression [asc | desc]

//查询Sno在[1,10]间的记录,按Sroomid升序排序
select * from Students.Student where Sno between 1 and 10 order by Sroomid;

6.3、连接查询

连接查询是把两个或两个以上的表按某个条件连接起来,从中选取需要的数据。连接查询是同时查询两个或两个以上的表时使用的。当不同的表中存在相同意义的列时,可通过该字段来连接这几个表。

MySQL支持不同的连接类型:交叉连接、内连接、自连接查询。

6.3.1 交叉连接查询

交叉查询是连接的最简单的类型,它不带where子句,返回被连接的两个或多个表所有数据行的笛卡尔积,返回结果集合中的数据行数等于第一个表中符合查询条件的数据行乘以第二个表中符合查询条件的数据行数。

代码语言:txt复制
语法格式:
select * from table1,table2;

//查询 Student表和Cource表 每一行两两组合成新的一行的结果
select * from Students.Student,Students.Cource;
6.3.2 内连接查询

内连接是最普通的连接类型,而且是最匀称的,因为它们要求构成连接的每一部分与每个表匹配,不匹配的行将被排除在最后的结果集之外。内连接的最常见的列子是相等连接,还有不等连接、自然连接,也就是连接后的表中的某个列与每个表的都相同。

在交叉连接的基础上添加where 子句可以实现内连接。

代码语言:txt复制
语法格式:
//列名列表:可以来自不同的表
select 列名列表 from 表1,表2 where 表1.列1 = 表2.列2;

//查询Student和StudentCourse表的记录,但是必须Student.Sno = StudentCourse.Sno
select * from Students.Student,Students.StudentCourse where Students.Student.Sno = Students.StudentCourse.Sno;

为了清晰,MySQL还允许在操作中使用 inner join ... on 和 cross join ... on 关键字 而不是使用逗号。

代码语言:txt复制
语法格式:
select 列名列表 from 表名1 inner join 表名2 on 表名1.列名1=表名2.列名2;

select 列名列表 from 表名1 cross join 表名2 on 表名1.列名1=表名2.列名2;

当表的名称过长或两个或多个表的列名相同时,可以重新为表指定名称。然后使用“表别名.列名”读取列的数据。

6.3.3 外连接查询

外连接查询可以查询两个或两个以上的表。外连接查询也需要通过指定字段列来进行连接。当该字段取值相等时,可以查询出该记录。而且,该字段列取值不相等的记录也可以查询出来。

可以将外连接查询分为:左连接查询和右连接查询。

代码语言:txt复制
语法格式:
//列名列表:可以来自不同的表
//左连接,join左边的表是主表,右连接,join右边的表是主表
//以某一个表为主表,进行关联查询,不管能不能关联上,主表的数据都会保留,关联不上的以null显示
select 列名列表 from 表名1 left | right join 表名2 on 表名1.列名1=表名2.列名2;

select * from Students.Student left join Students.StudentCourse on Students.Student.Sno = Students.StudentCourse.Sno;

内连接和外连接的区别: 内连接:取出连接表中匹配到的数据,主表数据都会保留,副表中匹配不到的不保留。 外连接:取出连接报中匹配到的数据,主表数据都会保留,副表中匹配不到也会保留,其值为null。

6.4、联合查询

union 用来把两个或两个以上select语句的查询结果输出连接成一个单独的结果集。大多数情况下,union 用来把查询产生的 结果集 添加到不同的表,用来创建包括所有结果的一个单独表。

使用 union 关键字时,数据库系统会将所有的查询结果合并到一起。然后去除相同的记录。而union all关键字只是简单地合并到一起,不会去重。

代码语言:txt复制
基本语法:
select 语句1
union | union all
select 语句2
union | union all
select 语句n
[order by order_expression]

在联合查询时,查询结果的列标题为第一个select语句的列标题。因此,要定义列标题必须在第一个select语句中定义。要对联合查询结果排序时,也必须使用第一个select语句中的列标题。

6.4.1、单张表联合查询
代码语言:txt复制
//联合查询Student表中Sno在[1,3]和[5,7]这两个范围的记录
select * from Students.Student where Sno between 1 and 3
	union select * from Students.Student where Sno between 5 and 7
6.4.2、多张表联合查询

union 关键字上下两个结果集的列数必须相等,否则会报错。最终合并的列名,由第一个select语句决定。

代码语言:txt复制
//将Student表中年龄小于19的Sname和Teachers表中的Tname合并
select Sname from Students.Student where Sage<19
	union select Tname from Teacher;
6.4.3、语句执行顺序

如果最后跟了order by、limit 子句,这些子句会等 union 将结果集合并之后再执行。

6.5、子查询

当查询条件使用的是另一个查询生成的值时,经常会产生新的情况,这是需要用到子查询。

子查询就是一个select查询是另一个查询的附属。就是将一个查询语句嵌套在另一个查询语句中。内层查询语句的查询结果,可以为外层查询语句提供查询条件。

子查询有很多种用法,可以在一个where 或having 子句中使用;可以与逻辑运算符 和 比较运算符使用;可以和union 一起使用,也可以与update 或 delete语句一起使用。

代码语言:txt复制
select * from Students.Student where Sno=(select max(Sno) from Students.StudentCourse where grade>90 or cno>3014);

select * from Students.Student where Sno in (select Sno from Students.StudentCourse where grade>90 or cno>3014);

where xxx = yyy 时,子查询的结果大于1个会报错,可以改成where xxx in yyy 或 where xxx = any yyy,这两个表达是同一个意思。 in() 比较关键字 判断某列的取值是否为指定值中的一个。

6.6、正则表达式查询

代码语言:txt复制
语法格式:

列名 regexp '匹配方式'

7、索引的使用

7.1、为什么使用索引

作用:主要是为了提高从表中检索数据的速度。由于数据存储在数据库表中,所以索引是创建在数据库表对象上的,由表中的一个或多个字段生成的键组成,这些键存储在数据结构(B-数或哈希表)中,通过MySQL可快速查找与键值相关联的字段。跟进索引的存储类型,可分为B型树索引(BTree)和哈希索引(hash)

innoDBh和MyISAM存储引擎支持Btree索引,Merroy存储引擎支持hash,默认为BTree索引。

使用场景:

代码语言:txt复制
创建索引可提供查询速度,但过多的索引则会占据许多磁盘空间。因此创建索引前要权衡利弊。
1、设置唯一性约束的字段,可更快通过该索引查到某条记录,比如学生表中的学号具有唯一性。
2、为经常需要排序、分组、联合操作的字段建立索引;比如经常需要order by、group by、distinct、union等操作的字段,排序会浪费很多时间,如果为其建立索引,可有效地避免排序操作。
3、经常被查询的字段,即再where子句中出现的字段。
4、尽量使用数据量少的索引;如果索引值很长,那么查询的速度会受到影响。列如对一个char(100)类型的字段进行全文检索需要的时间肯定比char(10)字段需要的时间多。
5、尽量使用前缀来索引;如果索引字段的值很长,最好使用值的前缀来索引。

以下场景不适合创建索引:

代码语言:txt复制
1、在查询中很少被使用的索引
2、拥有许多重复值的字段

索引的分类:

代码语言:txt复制
1、普通索引,就是在创建索引时,不附加任何限制条件(唯一、非空等)。该类型索引可创建在任务数据类型字段上。

2、唯一索引,即创建索引时,限制索引的值必须是唯一的。通过该类型索引可更快地查询某条记录。
* 所谓自动索引,指在表里设置完整性约束时,该表会被系统自动创建索引。
* 所谓手动索引,指手动在表上创建索引。
* 当设置表中某个字段设置主键或唯一完整性约束时,系统就会自动创建关联该字段的唯一索引。

3、全文索引,主要关联在数据类型为char、varchar和text的字段上,以便能够更加快速地查询数据量较大的字符串类型的字段。
* MySQL从3.23.23开始支持全文索引,只能在存储引擎为 MyISAM 的数据库表上创建全文索引。默认情况下,全文索引的搜索执行方式不区分大小写,如果全文索引所关联的字段为二进制数据类型,则以区分大小写的搜索方式执行。

4、单列索引,在表的单个字段上创建索引。单列索引只根据该字段进行索引。单列索引可以是普通索引,也可以是唯一性索引,还可以是全文索引。只有保证该索引只对应一个字段就可以。

5、多列索引,是指在创建索引时,所关联的字段不是一个字段,而是多个字段。可以通过这几个字段进行查询,但是只有查询条件中使用了这些字段中的第一个字段时,索引才会被使用。

6、空间索引,使用 spatial 参数可以设置索引为空间索引。只能建立在空间数据类型上,这样可提供系统获取空间数据的效率。MySQL中空间数据类型包括geometry、point、linestring、polygon等。目前只有MyISAM 存储引擎支持空间索引,而且索引的字段不能为空值。

7.2、索引的操作

1) 创建表时创建索引

代码语言:txt复制
语法格式:
create table table_name(
    属性名 数据类型 [完整性约束条件]
	[unique | fulltext | spatial] index|key [索引名](属性名1 [(长度)] [Asc|Desc])
) 
注意:MySQL支持的存储引擎每个表至少支持16个索引,总索引长度至少为256字节。

说明:index或key指定字段为索引,索引名一般index_开头,‘属性名1’表示用来指定所关联的字段名,‘长度’指定索引的长度,ASC|DESC指定升序或降序排序。

create table t_dept(
	deptno int,
	dname varchar(20),
	loc varchar(40),
	index index_deptno(deptno)
);

//验证表中索引是否创建成功
show create table t_dept;

//验证表中索引是否被使用,执行结果中若possible_keys和key字段的值都是创建的索引名index_deptno,说明索引已存在,而且已经开始启用
explain
	select * from t_dept where deptno=1;
代码语言:txt复制
1、创建普通索引
create table t_dept(
	deptno int,
	dname varchar(20),
	loc varchar(40),
	index index_deptno(deptno)
);

2、创建唯一性索引
语法格式和创建普通索引一样,在 index 前面加上unique就可以。

3、创建全文索引
create table t_dept(
	deptno int,
	dname varchar(20),
	loc varchar(40),
	fulltext index index_deptno(deptno)
) engine=myisam;

4、创建多列索引
语法格式:
create table table_name(
    属性名 数据类型
	index|key [索引名](属性名1 [(长度)] [Asc|Desc],
						.....
						属性名1 [(长度)] [Asc|Desc]
	)
) 

create table t_dept(
	deptno int,
	dname varchar(20),
	loc varchar(40),
	index index_deptno_loc(deptno,loc)
);

5、创建空间索引
平时很少用到。

2) 在已经存在的表上创建索引

代码语言:txt复制
语法格式:
create [unique | fulltext | spatial] index 索引名
	on 表名(属性名 [(长度)] [Asc|Desc])
代码语言:txt复制
1、创建单列索引
//查询时可以只查询 dname 的前4个字符,而不需要全部查询。
create index index_deptno on t_dname(dname(4));

2、创建唯一性索引
语法格式和创建普通索引一样,在 index 前面加上unique就可以。

3、创建全文索引

语法格式和创建普通索引一样,在 index 前面加上fulltext就可以。

4、创建多列索引
create index index_deptno on t_dept(deptno, dname);

5、创建空间索引
语法格式和创建普通索引一样,在 index 前面加上spatial就可以。

3) 通过SQL语句 alter table创建索引

代码语言:txt复制
语法格式:
alter table table_name
	add [unique | fulltext | spatial] index|key 索引名(属性名 [(长度)] [Asc|Desc])
	
alter table t_dept
	add index index_deptno(deptno);

7.3 删除索引

代码语言:txt复制
语法格式:
drop index index_name
	on table_name;

7.4 修改索引

代码语言:txt复制
语法格式:
alter table 表名 add [unique | fulltext | spatial] index
	索引名(属性名 [(长度)] [Asc|Desc])

8、视图

  • 视图是一张虚拟的表,其内容由查询语句来构成。视图将数据以表的形式提交给用户,却不存储数据。查询语句可以涉及多个表,因此一个视频可以包含多个表数据。
  • 视图所引用的表被称为基础表,对基础表来说,视图的作用相当于数据筛选。
  • 视图一经定义便存储在数据库中,与其对应的数据并没有像表那样又在数据库中再存储一份,通过视图看到的数据只是存放在基础表中的数据。
  • 视图被引用的时候才派生出数据,不占用空间。

使用视图的优点:

代码语言:txt复制
1、集中数据。简化用户的数据查询和处理。有时需要将多表数据集中到一起方便用户的数据查询和处理。
2、简化操作。用户不必了解复杂的数据库表结构,并且表的更改不影响用户对数据库的使用。
3、实现复杂的查询需求。复杂的查询可以进行问题分解,然后将创建多个视频获取数据,最后将视图联合起来得到需要的结果。
4、简化用户权限的管理。只需授予用户使用视图的权限,而不必指定用户只能使用表的特定列,也增加了安全性。
5、便于数据分享。各用户不必都定义各存储自己所需的数据,可共享数据库的数据,这样同样的数据只需存储一次。

8.1 视图的基本操作

8.1.1 创建视图
代码语言:txt复制
语法格式:
create [algorithm = {undefined | merge | temptable}]
view view_name as
select column_name(s) from table_name
[with [caccaded | local] check option ]

各个参数的含义如下:
(1)algorithm:可选参数,表示视图选择的算法。
(2)undefined:MySQL 将自动选择所要使用的算法。
(3)merge:将视图的语句与视图定义合并起来,使得视图定义的某一部分取代语句的对应的部分。
(4)temptable:将视图的结果存入临时表,然后使用临时表执行语句。
(5)view_name:指创建视图的名称,可包含其属性列表。
(6)column_name(s):指查询的字段,也就是视图的列名。
(7)table_name:指从哪几个表中获取数据
(8)with check option:可选参数,表示更新视图时要保证在视图的权限范围内。
(9)cascaded:在更新视图时满足所有相关视图和表的条件才进行更新
(10)local:在更新视图时满足该视图本身定义的条件即可更新。

注意:如果给定了 or replace 子句,该语句还能替换已有的视图,select_statement 它给出了视图的定义,该语句可从基表或其他视图进行选择。

系统提供的默认格式:
create view view_name
	as 查询语句;

//创建视图student_view	
create view student_view as select * from Students.Student;

//查看视图的结构
desc student_view;

//查询student_view视图数据
select * from student_view;
8.1.2 查看视图基本信息
代码语言:txt复制
语法格式:
show table status like '视图名';

show table status like 'student_view';
8.1.3 查看视图详细信息
代码语言:txt复制
语法格式:
show create view 视图名;

show create view student_view;
8.1.4 修改视图

视图的修改是指修改了数据表的定义,当视图定义的数据表字段发生变化时需要对视图进行修改以保证查询的正确进行。create or replace view 可以修改视图,当视图存在时进行修改,不存在时可以创建视图。

代码语言:txt复制
语法格式:
create or replace [algorithm = {undefined | merge | temptable}]
view view_name [(属性清单)] as
select column_name(s) from table_name
[with [caccaded | local] check option ];

各个参数的含义如下:
(1)属性清单:可选,指定了视图中各个属性的名词,在默认情况下与 select 语句中查询的属性相同。
(2)create or replace:可以替换成 alter 修改视图。只能修改已存在视图,不会创建。

//修改视图,视图有sno,sage,sroomid
create or replace view student_view(sno,sage,sroomid) as 
select Students.Student.Sno,Students.Student.Sage,Students.Student.Sroomid 
from Students.Student;
8.1.5 更新视图

使用insert、update、delete语句更新视图中的数据。

代码语言:txt复制
update student_view set sroomid=302 where sno=4;

//因为向视图插入数据会使对应表也插入数据,但原表一条记录中有的列不允许为空,所以无法插入。
insert into student_view values(10,19,305);

delete from student_view where sno=2;
8.1.6 删除视图

因为视图本身只是一个虚拟表,没有物理文件存在,所以删除视图并不会删除数据,只是删除视图的结构定义。

代码语言:txt复制
语法格式:
//使用if exists防止因不存在的视图而出错,给定了该子句时,将为每个不存在的视图生成NOTE.
drop view [if exists] view_name [,view_name1...]

drop view if exists student_view;

9、系统函数

mysql 数学函数

函数名称

作 用

abs

求绝对值

sqrt

求二次方根

mod

求余数

ceil 和 ceiling

两个函数功能相同,都是返回不小于参数的最小整数,即向上取整

floor

向下取整,返回值转化为一个bigint

rand

生成一个0~1之间的随机数,传入整数参数是,用来产生重复序列

round

对所传参数进行四舍五入

sign

返回参数的符号

pow 和 power

两个函数的功能相同,都是所传参数的次方的结果值

sin

求正弦值

asin

求反正弦值,与函数 sin 互为反函数

cos

求余弦值

acos

求反余弦值,与函数 cos 互为反函数

tan

求正切值

atan

求反正切值,与函数 tan 互为反函数

cot

求余切值

mysql 字符串函数

函数名称

作 用

length

计算字符串长度函数,返回字符串的字节长度

concat

合并字符串函数,返回结果为连接参数产生的字符串,参数可以使一个或多个

insert

替换字符串函数

lower

将字符串中的字母转换为小写

upper

将字符串中的字母转换为大写

left

从左侧字截取符串,返回字符串左边的若干个字符

right

从右侧字截取符串,返回字符串右边的若干个字符

trim

删除字符串左右两侧的空格

replace

字符串替换函数,返回替换后的新字符串

substring

截取字符串,返回从指定位置开始的指定长度的字符换

reverse

字符串反转(逆序)函数,返回与原始字符串顺序相反的字符串

mysql 日期和时间函数

函数名称

作 用

curdate 和 current_date

两个函数作用相同,返回当前系统的日期值

curtime 和 current_time

两个函数作用相同,返回当前系统的时间值

now 和  sysdate

两个函数作用相同,返回当前系统的日期和时间值

unix_timestamp

获取unix时间戳函数,返回一个以 unix 时间戳为基础的无符号整数

from_unixtime

将 unix 时间戳转换为时间格式,与unix_timestamp互为反函数

month

获取指定日期中的月份

monthname

获取指定日期中的月份英文名称

dayname

获取指定曰期对应的星期几的英文名称

dayofweek

获取指定日期对应的一周的索引位置值

week

获取指定日期是一年中的第几周,返回值的范围是否为 0〜52 或 1〜53

dayofyear

获取指定曰期是一年中的第几天,返回值范围是1~366

dayofmonth

获取指定日期是一个月中是第几天,返回值范围是1~31

year

获取年份,返回值范围是 1970〜2069

time_to_sec

将时间参数转换为秒数

sec_to_time

将秒数转换为时间,与time_to_sec 互为反函数

date_add 和 adddate

两个函数功能相同,都是向日期添加指定的时间间隔

date_sub 和 subdate

两个函数功能相同,都是向日期减去指定的时间间隔

addtime

时间加法运算,在原始时间上添加指定的时间

subtime

时间减法运算,在原始时间上减去指定的时间

datediff

获取两个日期之间间隔,返回参数 1 减去参数 2 的值

date_format

格式化指定的日期,根据参数返回指定格式的值

weekday

获取指定日期在一周内的对应的工作日索引

mysql 聚合函数

函数名称

作用

max

查询指定列的最大值

min

查询指定列的最小值

count

统计查询结果的行数

sum

求和,返回指定列的总和

avg

求平均值,返回指定列数据的平均值

group_concat

该函数会把每个分组中指定的字段值都显示出来。用于将多行合并成一行,返回一个由多个值组成的字符串

mysql 流程控制函数

函数名称

作用

if

判断,流程控制

ifnull

判断是否为空

case

搜索语句

不同进制的数字进行转换

函数名称

作用

ASCII(s)

返回字符串s的第一个字符的ASCII码

BIN(x)

返回x的二进制编码(十进制 转 二进制)

HEX(x)

返回x的十六进制编码

UNHEX(十六进制字符串)

十六进制 转 二进制

OCT(x)

返回x的八进制编码

9.1 流程控制函数

1、if(expr,v1,v2)函数

  如果表达式expr成立,返回结果v1;否则,返回结果v2。

2、ifnull(v1,v2)函数

  如果v1的值不为null,则返回v1,否则返回v2。

3、case

代码语言:txt复制
语法1:

case 
  when e1
  then v1
  when e2
  then e2
  ...
  else vn
end
  case表示函数开始,end表示函数结束。如果e1成立,则返回v1,如果e2成立,则返回v2,当全部不成立则返回vn,而当有一个成立之后,后面的就不执行了。

select case 
  when 1 > 0
  then '1 > 0'
  when 2 > 0
  then '2 > 0'
  else '3 > 0'
  end
->1 > 0
代码语言:txt复制
语法2:

case expr 
  when e1 then v1
  when e1 then v1
  ...
  else vn
end
  如果表达式expr的值等于e1,返回v1;如果等于e2,则返回e2。否则返回vn。

select case 1 
  when 1 then '我是1'
  when 2 then '我是2'
else '你是谁'

9.2 其他函数

9.2.1、格式化函数format(x,n)

format(x,n)函数可以将数字x进行格式化,将x保留到小数点后n位。

9.2.2、IP地址与数字相互转换的函数

inet_aton(ip)函数可以将ip地址转换为数字表示;ip值需要加上引号;

inet_ntoa(n)函数可以将数字n转换成ip形式。

代码语言:txt复制
select inet_aton('192.168.0.1')
    ->3232235521
    
select inet_ntoa(3232235521)
    ->192.168.0.1
9.2.3、改变字符集的函数

convert(s using cs)函数将字符串s的字符集变成cs。

代码语言:txt复制
select charset('abc')
    ->utf-8    

select charset(convert('abc' using gbk))
    ->gbk
9.2.4、转换数据类型

cast(x as type)和convert(x,type)

这两个函数只对binary、char、date、datetime、time、signed integer、unsigned integer。

代码语言:txt复制
select cast('342' as unsigned integer)   1
    ->343
//mysql能默认转换
select '123'   1
    ->124

select cast(now() as date)
  ->2023-11-30
9.2.5、加密函数

加密函数是mysql用来对数据进行加密的函数。

1、password(str)

该函数可以对字符串str进行加密,一般情况下,password(str)用于给用户的密码加密。

MySQL 8.0中已经不起作用。

代码语言:txt复制
select password('123')

2、md5

md5(str)函数可以对字符串str进行散列,可以用于一些普通的不需要解密的数据加密。

代码语言:txt复制
select md5('432')

3、encode(str,pswd_str) 与 decode(cry_str,pswd_str)

encode函数可以使用加密密码pswd_str来加密字符串str,加密结果是二进制数,需要使用blob类型的字段保存。该函数与decode是一对,需要同样的密码才能够解密。

代码语言:txt复制
select encode('123','fdf')
   
select decode(';vx','fdf')
   

4、aes_encrypt(字符串,秘钥)和 aes_decrypt(字符串,秘钥)

代码语言:txt复制
//加密
select TO_BASE64(AES_ENCRYPT('暖乎乎123','323241'));

//解密
//结果是blob类型,显示不了
select aes_decrypt(FROM_BASE64('uSWupDerTa8oLm0wijcmiA=='),'323241');

//可以 使用 convert 设置 字符集为utf-8,就可以正常显示
//这种转换只适用于存储文本类型数据的 blob 列
SELECT convert(aes_decrypt(FROM_BASE64('uSWupDerTa8oLm0wijcmiA=='),'323241') using utf8) as text_data

1、使用base32和base64,将二进制转换为32位或64位,会大大减少转换后的字符串长度,减少对于数据库存储空间的浪费。

2、如果从 存储空间 考虑,建议转换为64进制,两个进制转换上对于 服务器性能 和 加密速度 上有一定的区别,可以自行测试。

3、AES加密后的数据为二进制,不可读,不便于查询出来后作为中间数据进行存储处理。可以将加密后的二进制数据转换为32或64进制后再进行存储。

0 人点赞