MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理

文章目录

  • 表的内连和外连
    • 内连接
    • 外连接
  • 索引特性
    • 索引概述
    • 基本原理
    • 创建索引
    • 查询索引
    • 删除索引
    • 索引创建原则
  • 事务管理
    • 事务基本操作
    • 事务的隔离级别
    • 事务的ACID特性
  • 视图
  • 用户管理
    • 用户
    • 数据库的权限

表的内连和外连

表的连接分为内连和外连

内连接

内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,我们前面学习的查询都是内连接,也是在开发过程中使用的最多的连接查询。
语法:

select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件;
//显示SMITH的名字和部门名称
-- 用前面的where写法
select ename, dname from EMP, DEPT where EMP.deptno=DEPT.deptno and ename='SMITH';
-- 用标准的内连接写法
select ename, dname from EMP inner join DEPT on EMP.deptno=DEPT.deptno and
ename='SMITH';

外连接

外连接分为左外连接和右外连接.

左外连接
如果联合查询,左侧的表完全显示我们就说是左外连接。
语法:

select 字段名 from 表名1 left join 表名2 on 连接条件

右外连接
如果联合查询,右侧的表完全显示我们就说是右外连接。
语法:

select 字段 from 表名1 right join 表名2 on 连接条件;

举例:

-- 建两张表
create table stu (id int, name varchar(30)); -- 学生表
insert into stu values(1,'jack'),(2,'tom'),(3,'kity'),(4,'nono');
create table exam (id int, grade int); -- 成绩表
insert into exam values(1, 56),(2,76),(11, 8);

MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理_第1张图片

  • 查询所有学生的成绩,如果这个学生没有成绩,也要将学生的个人信息显示出来
    左外连接,以左边的表为基准:
    MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理_第2张图片
  • 对stu表和exam表联合查询,把所有的成绩都显示出来,即使这个成绩没有学生与它对应,也要显示出来
  • 右外连接,以右边的表为基准:
    MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理_第3张图片

索引特性

索引概述

在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。
索引提供指向存储在表的指定列中的数据值的指针,然后根据你指定的排序顺序对这些指针排序。数据库使用索引以找到特定值,然后顺指针找到包含该值的行。这样可以使对应于表的SQL语句执行得更快,可快速访问数据库表中的特定信息。

优点:提高数据库的性能,不用加内存,不用改程序,不用调sql,只要执行正确的create index ,查询速度就可能提高成百上千倍。
缺点:查询速度的提高是以插入、更新、删除的速度为代价的,这些写操作,增加了大量的IO(更新索引)。所以它的价值,在于提高一个海量数据的检索速度。

常见索引分为:
主键索引(primary key)
唯一索引(unique)
普通索引(index)
全文索引(fulltext)–解决中文索引问题。

基本原理

索引理论的深度理解参见推荐书籍:《数据库系统概念》的第11章。
根据索引把元素组织成树形结构查询(空间换时间):
MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理_第4张图片
索引的说明:

  • 占用磁盘空间
  • 当添加一条记录,除了添加到表中,还要维护二叉树,速度有影响,但不大。
  • 当我们添加一个索引,不能够解决所有查询问题,需要分别给字段建立索引;例如 select * from EMP whereename=‘abcdef’;索引是以空间换时间。

创建索引

1.创建主键索引

第一种:
-- 在创建表的时候,直接在字段名后指定 primary key
create table user1(id int primary key, name varchar(30));

第二种:
-- 在创建表的最后,指定某列或某几列为主键索引
create table user2(id int, name varchar(30), primary key(id));

第三种:
create table user3(id int, name varchar(30));
-- 创建表以后再添加主键
alter table user3 add primary key(id);

主键索引的特点:

  • 一个表中,最多有一个主键索引,当然可以使用复合主键
  • 主键索引的效率高(主键不可重复)
  • 创建主键索引的列,它的值不能为null,且不能重复
  • 主键索引的列基本上是int

2. 唯一索引的创建

第一种:
-- 在表定义时,在某列后直接指定unique唯一属性。
create table user4(id int primary key, name varchar(30) unique);

第二种:
-- 创建表时,在表的后面指定某列或某几列为unique
create table user5(id int primary key, name varchar(30), unique(name));

第三种
create table user6(id int primary key, name varchar(30);
-- 创建表以后再添加唯一键
alter table user6 add unique(name);

唯一索引的特点:

  • 一个表中,可以有多个唯一索引
  • 查询效率高
  • 如果在某一列建立唯一索引,必须保证这列不能有重复数据
  • 如果一个唯一索引上指定not null,等价于主键索引

3. 普通索引的创建

第一种:
create table user8(id int primary key,
name varchar(20),
email varchar(30),
index(name) --在表的定义最后,指定某列为索引
);

第二种:
create table user9(id int primary key, name varchar(20), email varchar(30));
alter table user9 add index(name); --创建完表以后指定某列为普通索引

第三种:
create table user10(id int primary key, name varchar(20), email varchar(30));
-- 创建一个索引名为 idx_name 的索引
create index idx_name on user10(name);

普通索引的特点:

  • 一个表中可以有多个普通索引,普通索引在实际开发中用的比较多
  • 如果某列需要创建索引,但是该列有重复的值,那么我们就应该使用普通索引

4.全文索引的创建
当对文章字段或有大量文字的字段进行检索时,会使用到全文索引。MySQL提供全文索引机制,但是有要求,要求表的存储引擎必须是MyISAM,而且默认的全文索引支持英文,不支持中文。如果对中文进行全文检索,可以使用sphinx的中文版(coreseek)。

举例:

CREATE TABLE articles (
	id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
	title VARCHAR(200),
	body TEXT,
	FULLTEXT (title,body)
)engine=MyISAM;

//插入测试数据
INSERT INTO articles (title,body) VALUES
	('MySQL Tutorial','DBMS stands for DataBase ...'),
	('How To Use MySQL Well','After you went through a ...'),
	('Optimizing MySQL','In this tutorial we will show ...'),
	('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
	('MySQL vs. YourSQL','In the following database comparison ...'),
	('MySQL Security','When configured properly, MySQL ...');
  • 查询有没有database数据
    1.使用之前普通的查询方式,未使用全文索引:
    MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理_第5张图片
    可以用explain工具看一下,判断是否使用到索引:
    MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理_第6张图片
    2.使用全文索引查询
    MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理_第7张图片

查询索引

第一种方法: show keys from 表名
MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理_第8张图片
第二种方法: show index from 表名;
第三种方法(信息比较简略): desc 表名;

删除索引

第一种方法

删除主键索引: alter table 表名 drop primary key;

第二种方法

其他索引的删除: alter table 表名 drop index 索引名; 
索引名就是show keys from 表名中的 Key_name 字段

mysql> alter table user10 drop index idx_name;

第三种方法:

// drop index 索引名 on 表名
mysql> drop index name on user8;

索引创建原则

  • 比较频繁作为查询条件的字段应该创建索引
  • 唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件
  • 更新非常频繁的字段不适合作创建索引
  • 不会出现在where子句中的字段不该创建索引

事务管理

事务就是一组DML语句组成,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。MySQL提供一种机制,保证我们达到这样的效果。事务还规定不同的客户端看到的数据是不相同的。

MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理_第9张图片
类似于线程安全的例子,而这里的事务隔离机制便可以理解为互斥锁的概念。

事务基本操作

基本语法:

开始一个事务
start transaction;

创建一个保存点
savepoint 保存点名;

回到保存点(根据具体情况)
rollback to 保存点名;

举例:
创建余额表:

create table account(
	id int primary key,
	name varchar(50) not null default '',
	balance decimal(10, 2) not null default 0.0
);
mysql> start transaction; --开启事务
Query OK, 0 rows affected (0.00 sec)

mysql> savepoint aa; --设置保存点aa
Query OK, 0 rows affected (0.00 sec)

mysql> insert into account values(1, '张三', 10); --添加一条记录
Query OK, 1 row affected (0.00 sec)

mysql> savepoint bb; -- 设置保存点bb
Query OK, 0 rows affected (0.00 sec)

mysql> insert into account values(2, '李四', 10000); --再添加一条记录
Query OK, 1 row affected (0.00 sec)

mysql> select * from account; --两条记录都在了
+----+--------+----------+
| id | name | balance |
+----+--------+----------+
| 1 | 张三   | 10.00   |
| 2 | 李四   | 10000.00 |
+----+--------+----------+
2 rows in set (0.00 sec)

mysql> rollback to bb; -- 发现后来添加这一条记录是误操作。所以回滚到bb状态
Query OK, 0 rows affected (0.01 sec)

mysql> select * from account; -- 第二条记录没有了
+----+--------+---------+
| id | name | balance |
+----+--------+---------+
| 1 | 张三  | 10.00  |
+----+--------+---------+
1 row in set (0.03 sec)

事务操作注意事项

  • 如果没有设置保存点,也可以回滚,只能回滚到事务的开始。直接使用 rollback(前提是事务还没有提交)
  • 如果一个事务被提交了(commit),则不可以回退(rollback)
  • 可以选择回退到哪个保存点
  • InnoDB支持事务,MyISAM不支持事务

事务的隔离级别

当我们有多个客户端同时操作数据库的某张表,如何进行隔离操作?MySQL提供了隔离级别。
当MySQL表被多个线程或者客户端开启各自事务操作数据库中的数据时,MySQL提供了一种机制,可以让不同的事务在操作数据时,具有隔离性。从而保证数据的一致性。

无隔离性的问题
1.脏读
是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
2.不可重复读
是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。(即不能读到相同的数据内容)
3.幻读
是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

注意:
不可重复读的重点是修改:同样的条件, 你读取过的数据,再次读取出来发现值不一样了 幻读的重点在于新增或者删除:同样的条件, 第1次和第2次读出来的记录数不一样。

事务的隔离级别

MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理_第10张图片
说明:mysql默认的隔离级别是可重复读,一般情况下不要修改

设置事务的隔离级别
语法:

set session transaction isolation level read uncommitted; //设置为读未提交隔离级别

查看当前的隔离级别:

mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+

隔离级别:可串行化 案例
MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理_第11张图片
当客户端A在执行select过程中,DBMS会对库加锁,如果这时客户端B执行插入,只要还没释放锁,插入不进去,会将B的update语句放入等待队列,直到释放了锁或超时。

事务的ACID特性

原子性(Atomicity):
事务是应用中最小的执行单位,就如原子是自然界的最小颗粒,具有不可再分的特征一样,事务是应用中不可再分的最小逻辑执行体。(只有两个结果:要么成功,要么失败)
一致性(Consistency):
事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务成功提交的结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中断,而该未完全完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确(不一致)的状态。因此一致性是通过原子性来保证的。
隔离性(Isolation):
各个事务的执行互不干扰,任意一个事务的内部操作对其他并发事务都是隔离的。也就是说,并发执行的事务之间不能看到对方的中间状态,并发执行的事务之间不能互相影响。
持久性(Durability):
持久性是指一个事务一旦被提交,它对数据库所做的改变都要记录到永久存储其中(如:磁盘)。

视图

视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。视图的数据变化会影响到基表,基表的数据变化也会影响到视图。

基本使用
语法:

create view 视图名 as select语句;

用法与以前表操作一样,但是视图的数据变化会影响到基表,基表的数据变化也会影响到视图。

删除试图:

drop view 视图名;

视图规则和限制

  • 与表一样,必须唯一命名(不能出现同名视图或表名)
  • 创建视图数目无限制,但要考虑复杂查询创建为视图之后的性能影响
  • 视图不能添加索引,也不能有关联的触发器或者默认值
  • 视图可以提高安全性,必须具有足够的访问权限
  • order by 可以用在视图中,但是如果从该视图检索数据select 中也含有order by ,那么该视图中的order by 将被覆盖
  • 视图可以和表一起使用

用户管理

如果我们只能使用root用户,这样存在安全隐患。这时,就需要使用MySQL的用户管理。
MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理_第12张图片
张三只能操纵mytest这个库,李四只能操纵msg这个库。如果给他们root账户,那他们就可以操纵所有的库,风险太大。

用户

用户信息:MySQL中的用户,都存储在系统数据库mysql的user表中

mysql> select host,user,authentication_string from user;
+-----------+---------------+-------------------------------------------+
| host |	 user 			| authentication_string |
+-----------+---------------+-------------------------------------------+
| localhost | root 			| *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| localhost | mysql.session | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| localhost | mysql.sys 	| *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
+-----------+---------------+-------------------------------------------+

字段解释:
host:表示这个用户可以从哪个主机登陆,如果是localhost,表示只能从本机登陆
user:用户名
authentication_string:用户密码通过password函数加密后的
*_priv:用户拥有的权限

创建用户
语法:

create user '用户名'@'登陆主机/ip' identified by '密码';

删除用户

drop user '用户名'@'主机名'

修改用户密码

自己改自己密码

set password=password('新的密码');

root用户修改指定用户的密码

set password for '用户名'@'主机名'=password('新的密码');

数据库的权限

MySQL数据库提供的权限列表:
MySQL数据库(四)表的内外连接、索引、事务管理、视图、用户管理_第13张图片
给用户授权
刚创建的用户没有任何权限。需要给用户授权。
语法:

grant 权限列表 on 库.对象名 to '用户名'@'登陆位置' [identified by '密码']

说明:
权限列表,多个权限用逗号分开
grant select on ...    --单个权限
grant select, delete, create on ....    多个权限
grant all [privileges] on ... -- 表示赋予该用户在该对象上的所有权限

*.* : 代表本系统中的所有数据库的所有对象(表,视图,存储过程等)
库.* : 表示某个数据库中的所有数据对象(表,视图,存储过程等)

identified by可选。 如果用户存在,赋予权限的同时修改密码,如果该用户不存在,就是创建用户

注意:如果发现赋权限后,没有生效,执行如下指令:

flush privileges;

回收权限
语法:

revoke 权限列表 on 库.对象名 from '用户名'@'登陆位置'

你可能感兴趣的:(MySQL数据库)