mysql数据库知识总结-02

1. 表的增删改查

  • 现有以下学生表:
    在这里插入图片描述

插入是否更新

  • 可能由于主键或者唯一键对应的值已经存在而导致插入失败
  • 可以选择性的进行同步更新操作
insert into students(id, sn, name) values (100,10010,'唐大师') 
on duplicate key update sn = 10010, name = '唐大师';
  • 如果插入冲突,就会按照update后面的语句更新数据

替换

  • 主键 或者 唯一键 没有冲突,则直接插入;
  • 主键 或者 唯一键 如果冲突,则删除后再插入
replace into students (sn, name) values (20001, '曹阿瞒');

select列

1. 全列查询

select * from students;

2. 指定列查询

select sn,name from students;

3. 查询字段为表达式

select sn+10,name from students;

4. 为查询结果指定别名

select sn as 学号,name from students;

5. 结果去重

select distinct qq from students;

where条件

比较运算符:
在这里插入图片描述
逻辑运算符:
在这里插入图片描述

结果排序

  • asc 为升序(从小到大)
  • desc 为降序(从大到小)
  • 默认为 asc
  • 例如按照学号降序排序
select *from students order by sn desc;

筛选分页结果

  • 从s号下标(即第s+1条数据)开始,筛选n条结果
//方法一:
select *from students limit s,n;
  • 如果limit后面只跟一个数字,则默认s为0,从0号下标开始筛选
  • 还有另一种写法。表示筛选n条结果,从s号下标开始
//方法二:
select *from students limit n offset s;

update

  • 将孙悟空的qq更改为666
update tb_name set column = expr [, column = expr ...] [where ...] [order by ...] [limit ...]

delete

delete from tb_name [where ...] [order by ...] [limit ...]

截断表

truncate [table] tb_name

注意:这个操作慎用

  1. 只能对整表操作,不能像 DELETE 一样针对部分数据操作;
  2. 实际上 MySQL 不对数据操作,所以比 DELETE 更快
  3. 会重置 AUTO_INCREMENT 项

插入查询结果

insert into tb_name [(column [, column ...])] select ...
  • 例如现在要将表中的重复数据去重
-- 创建一张空表 no_duplicate_table,结构和 duplicate_table 一样 
CREATE TABLE no_duplicate_table LIKE duplicate_table; 
Query OK, 0 rows affected (0.00 sec) 

-- 将 duplicate_table 的去重数据插入到 no_duplicate_table
INSERT INTO no_duplicate_table SELECT DISTINCT * FROM duplicate_table; 
Query OK, 3 rows affected (0.00 sec) 
Records: 3 Duplicates: 0 Warnings: 0 

-- 通过重命名表,实现原子的去重操作 
RENAME TABLE duplicate_table TO old_duplicate_table, no_duplicate_table TO duplicate_table; 
Query OK, 0 rows affected (0.00 sec)

group by子句的使用

在select中使用group by 子句可以对指定列进行分组查询

select column1, column2, .. from table group by column;

2. 函数

聚合函数

在这里插入图片描述

日期函数

1. current_date()

  • 获得年月日
    在这里插入图片描述

2. current_time()

  • 获得时分秒
    在这里插入图片描述

3. current_timestamp()

  • 获得时间戳
    在这里插入图片描述

4. date_add(date, interval n type)

  • 在日期的基础上加日期
    在这里插入图片描述

5. date_sub(date, interval n type);

  • 在日期的基础上减去时间
    在这里插入图片描述

6. datediff(date1, date2);

  • 计算两个日期之间相差多少天:
    在这里插入图片描述

字符串函数

1. charset(str)

  • 返回字符串字符集
    在这里插入图片描述

2. concat(string s, …)

  • 连接字符串
    在这里插入图片描述

3. length(string)

  • 求字符串占用的字节数

4. replace(str,search_str,replace_str)

  • 在str中用replace_str替换search_str
    在这里插入图片描述

5. substring(str,pos,len)

  • 从str的pos开始,取len个字符
    在这里插入图片描述

6. lcase(string)

  • 转换成小写
  • ucase(string)转大写
    在这里插入图片描述

数学函数

1. 绝对值

select abs(-100.2);

2. 向上取整

select ceiling(23.04);

3. 向下取整

select floor(23.7);

4. 保留2位小数位数(小数四舍五入)

select format(12.3456, 2);

5. 产生随机数

select rand();

其他函数

1. user() 查询当前用户
在这里插入图片描述
2. md5(str)对一个字符串进行md5摘要,摘要后得到一个32位字符串
在这里插入图片描述
3. database()显示当前正在使用的数据库
在这里插入图片描述
4. password()函数,MySQL数据库使用该函数对用户加密
在这里插入图片描述
5. ifnull(val1, val2) 如果val1为null,返回val2,否则返回val1的值
在这里插入图片描述

3. 复合查询

多表查询

  • 显示部门号为10的部门名,员工名和工资
select ename, sal,dname from EMP, DEPT where EMP.deptno=DEPT.deptno and DEPT.deptno = 10;

自连接

自连接是指在同一张表连接查询

  • 使用的子查询
select empno,ename from emp where emp.empno=(select mgr from emp where ename='FORD');
  • 使用多表查询(自查询)
//使用到表的别名 
select leader.empno,leader.ename from emp leader, emp worker where leader.empno = worker.mgr and worker.ename='FORD';

子查询

  • 子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询

单列子查询

  • 显示SMITH同一部门的员工
select * from EMP WHERE deptno = (select deptno from EMP where ename='smith');

多行子查询

  • in关键字;查询和10号部门的工作相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的
select ename,job,sal,empno from emp where job in (select distinct job from emp where deptno=10) and deptno<>10;
  • all关键字;显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号
select ename, sal, deptno from EMP where sal > all(select sal from EMP where deptno=30);
  • any关键字;显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号
select ename, sal, deptno from EMP where sal > any(select sal from EMP where deptno=30);

多列子查询

  • 单行子查询是指子查询只返回单列,单行数据;多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询则是指查询返回多个列数据的子查询语句
  • 例如:查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人
select ename from EMP where (deptno, job)=(select deptno, job from EMP where ename='SMITH') and ename <> 'SMITH';

在from子句中使用子查询

子查询语句出现在from子句中。这里要用到数据查询的技巧,把一个子查询当做一个临时表使用。

  • 显示高于自己部门平均工资的员工的姓名、部门、工资、平均工资
//获取各个部门的平均工资,将其看作临时表 
select ename, deptno, sal, format(asal,2) from EMP, (select avg(sal) asal, deptno dt from EMP group by deptno) tmp where EMP.sal > tmp.asal and EMP.deptno=tmp.dt;
  • 查找每个部门工资最高的人的姓名、工资、部门、最高工资
select EMP.ename, EMP.sal, EMP.deptno, ms from EMP, (select max(sal) ms, deptno from EMP group by deptno) tmp where EMP.deptno=tmp.deptno and EMP.sal=tmp.ms;
  • 显示每个部门的信息(部门名,编号,地址)和人员数量
  • 方法1:使用多表
select DEPT.dname, DEPT.deptno, DEPT.loc,count(*) '部门人数' from EMP, DEPT where EMP.deptno=DEPT.deptno group by DEPT.deptno,DEPT.dname,DEPT.loc;
  • 方法2:使用子查询
-- 1. 对EMP表进行人员统计 
select count(*), deptno from EMP group by deptno; 
-- 2. 将上面的表看作临时表 
select DEPT.deptno, dname, mycnt, loc from DEPT, (select count(*) mycnt, deptno from EMP group by deptno) tmp where DEPT.deptno=tmp.deptno;

合并查询

  • 在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all

union

  • 该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。

union all

  • 该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。

4. 表的内连和外连

内连接

  • 内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,也是在开发过程中使用的最多的连接查询。
select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件;

例如:

  • 显示SMITH的名字和部门名称
-- 用前面的写法 
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';

2. 外连接

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

(1)左外连接

  • 如果联合查询,左侧的表完全显示我们就说是左外连接。
  • 当左边表和右边表没有匹配时,也会显示左边表的数据
select 字段名 from 表名1 left join 表名2 on 连接条件

(2)右外链接

  • 如果联合查询,右侧的表完全显示我们就说是右外连接。
  • 当右边表和左边表没有匹配时,也会显示右边表的数据
select 字段 from 表名1 right join 表名2 on 连接条件;

5. 索引特性

索引:提高数据库的性能,索引是物美价廉的东西了。不用加内存,不用改程序,不用调sql,只要执行正确的create index ,查询速度就可能提高成百上千倍。但是天下没有免费的午餐,查询速度的提高是以插入、更新、删除的速度为代价的,这些写操作,增加了大量的IO。所以它的价值,在于提高一个海量数据的检索速度。

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

索引原理

  • 索引会形成一棵二叉树
  • 索引的说明
    • 占用磁盘空间
    • 当添加一条记录,除了添加到表中,还要维护二叉树,速度有影响,但不大。
    • 当我们添加一个索引,不能够解决所有查询问题,需要分别给字段建立索引;可能需要多个索引;
    • 索引是以空间换时间

创建主键索引

方法一:

-- 在创建表的时候,直接在字段名后指定 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

唯一索引的创建

方法一:

-- 在表定义时,在某列后直接指定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,等价于主键索引

普通索引的创建

方法一:

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);

普通索引的特点:

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

全文索引的创建

  • 当对文章字段或有大量文字的字段进行检索时,会使用到全文索引。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数据
  • 如果使用如下查询方式,虽然查询出数据,但是没有使用到全文索引

  • 可以用explain工具看一下,是否使用到索引

在这里插入图片描述

//key为null表示没有用到索引
  • 如何使用全文索引呢?
    在这里插入图片描述
  • 通过explain来分析这个sql语句
    在这里插入图片描述
//key用到了title,使用了全文索引

查询索引

  • 第一种方法: show keys from 表名
    在这里插入图片描述
  • 第二种方法: show index from 表名;
  • 第三种方法: desc 表名;

删除索引

  • 第一种方法-删除主键索引:
alter table 表名 drop primary key;
  • 第二种方法-其他索引的删除:
alter table 表名 drop index 索引名; 

索引名就是show keys from 表名中的 Key_name 字段

alter table user10 drop index idx_name;
  • 第三种方法方法: drop index 索引名 on 表名
drop index name on user8;

索引创建原则

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

6. 事务管理

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

  • 创建测试表

create table account( 
	id int primary key, 
	name varchar(50) not null default '', 
	balance decimal(10, 2) not null default 0.0 
);
  • 开始一个事务
start transaction;
  • 创建一个保存点
savepoint 保存点名;
  • 回到保存点(根据具体情况)
rollback to 保存点名;
  • 代码演示
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不支持事务
  • 开始事务可以使 start transaction

事务的隔离级别

  • 当MySQL表被多个线程或者客户端开启各自事务操作数据库中的数据时,MySQL提供了一种机制,可以让不同的事务在操作数据时,具有隔离性。从而保证数据的一致性。
  • 无隔离性的问题:脏读,不可重复读,幻读;

在这里插入图片描述

  • 设置事务的隔离级别
set session transaction isolation level read uncommitted;
  • 查看当前的隔离级别:
    在这里插入图片描述
  • mysql默认的隔离级别是可重复读

事务的ACID特性

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

7. 视图

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

创建视图

create view 视图名 as select语句;

删除视图

drop view 视图名;

注意

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

8. 用户管理

创建用户

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

例如

create user 'llmj'@'localhost' identified by '123456';

删除用户

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

在这里插入图片描述

  • 直接给个用户名,不能删除,它默认是%,表示所有地方可以登陆的用户

修改用户密码

1. 自己改自己密码

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

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

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

数据库的权限

  • 刚创建的用户没有任何权限。需要给用户授权。

给用户授权

grant 权限列表 on 库.对象名 to '用户名'@'登陆位置' [identified by '密码']
  • 权限列表,多个权限用逗号分开
grant select, delete, create on .... 
grant all [privileges] on ... -- 表示赋予该用户在该对象上的所有权限
  • 如果发现赋权限后,没有生效,执行如下指令:
flush privileges;

回收权限

revoke 权限列表 on 库.对象名 from '用户名'@'登陆位置';
-- 回收litao对数据库的所有权限 
revoke all on mytest.DEPT from 'litao'@'localhost';
发布了161 篇原创文章 · 获赞 52 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_42837885/article/details/103709050