表的连接分为内连和外连
内连接实际上就是利用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);
在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。
索引提供指向存储在表的指定列中的数据值的指针,然后根据你指定的排序顺序对这些指针排序。数据库使用索引以找到特定值,然后顺指针找到包含该值的行。这样可以使对应于表的SQL语句执行得更快,可快速访问数据库表中的特定信息。
优点:提高数据库的性能,不用加内存,不用改程序,不用调sql,只要执行正确的create index ,查询速度就可能提高成百上千倍。
缺点:查询速度的提高是以插入、更新、删除的速度为代价的,这些写操作,增加了大量的IO(更新索引)。所以它的价值,在于提高一个海量数据的检索速度。
常见索引分为:
主键索引(primary key)
唯一索引(unique)
普通索引(index)
全文索引(fulltext)–解决中文索引问题。
索引理论的深度理解参见推荐书籍:《数据库系统概念》的第11章。
根据索引把元素组织成树形结构查询(空间换时间):
索引的说明:
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);
主键索引的特点:
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);
唯一索引的特点:
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 ...');
第一种方法: show keys from 表名
第二种方法: 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;
事务就是一组DML语句组成,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。MySQL提供一种机制,保证我们达到这样的效果。事务还规定不同的客户端看到的数据是不相同的。
类似于线程安全的例子,而这里的事务隔离机制便可以理解为互斥锁的概念。
基本语法:
开始一个事务
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)
事务操作注意事项
当我们有多个客户端同时操作数据库的某张表,如何进行隔离操作?MySQL提供了隔离级别。
当MySQL表被多个线程或者客户端开启各自事务操作数据库中的数据时,MySQL提供了一种机制,可以让不同的事务在操作数据时,具有隔离性。从而保证数据的一致性。
无隔离性的问题
1.脏读
是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
2.不可重复读
是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。(即不能读到相同的数据内容)
3.幻读
是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
注意:
不可重复读的重点是修改:同样的条件, 你读取过的数据,再次读取出来发现值不一样了 幻读的重点在于新增或者删除:同样的条件, 第1次和第2次读出来的记录数不一样。
事务的隔离级别
说明:mysql默认的隔离级别是可重复读,一般情况下不要修改
设置事务的隔离级别
语法:
set session transaction isolation level read uncommitted; //设置为读未提交隔离级别
查看当前的隔离级别:
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+
隔离级别:可串行化 案例
当客户端A在执行select过程中,DBMS会对库加锁,如果这时客户端B执行插入,只要还没释放锁,插入不进去,会将B的update语句放入等待队列,直到释放了锁或超时。
原子性(Atomicity):
事务是应用中最小的执行单位,就如原子是自然界的最小颗粒,具有不可再分的特征一样,事务是应用中不可再分的最小逻辑执行体。(只有两个结果:要么成功,要么失败)
一致性(Consistency):
事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务成功提交的结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中断,而该未完全完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确(不一致)的状态。因此一致性是通过原子性来保证的。
隔离性(Isolation):
各个事务的执行互不干扰,任意一个事务的内部操作对其他并发事务都是隔离的。也就是说,并发执行的事务之间不能看到对方的中间状态,并发执行的事务之间不能互相影响。
持久性(Durability):
持久性是指一个事务一旦被提交,它对数据库所做的改变都要记录到永久存储其中(如:磁盘)。
视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。视图的数据变化会影响到基表,基表的数据变化也会影响到视图。
基本使用
语法:
create view 视图名 as select语句;
用法与以前表操作一样,但是视图的数据变化会影响到基表,基表的数据变化也会影响到视图。
删除试图:
drop view 视图名;
视图规则和限制
如果我们只能使用root用户,这样存在安全隐患。这时,就需要使用MySQL的用户管理。
张三只能操纵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数据库提供的权限列表:
给用户授权
刚创建的用户没有任何权限。需要给用户授权。
语法:
grant 权限列表 on 库.对象名 to '用户名'@'登陆位置' [identified by '密码']
说明:
权限列表,多个权限用逗号分开
grant select on ... --单个权限
grant select, delete, create on .... 多个权限
grant all [privileges] on ... -- 表示赋予该用户在该对象上的所有权限
*.* : 代表本系统中的所有数据库的所有对象(表,视图,存储过程等)
库.* : 表示某个数据库中的所有数据对象(表,视图,存储过程等)
identified by可选。 如果用户存在,赋予权限的同时修改密码,如果该用户不存在,就是创建用户
注意:如果发现赋权限后,没有生效,执行如下指令:
flush privileges;
回收权限
语法:
revoke 权限列表 on 库.对象名 from '用户名'@'登陆位置';