Mysql的运用

SQL

概述

Structured Query Language 结构化查询语言,是对数据库进行操作的一种语言。

SQL语句的分类

Data Definition Language 数据定义语言(定义数据库、表、列等,命令create drop alter等)

Data Manipulation Language 数据操作语言(增删改数据库中的数据,命令:insert delete update等)

Data Query Language 查询语言(查询数据库中数据表的数据,命令:select where等)

Data Control Language 控制语言(定义数据库的访问权限和安全等级以及创建用户,命令:grant  revoke等)

Transaction Control Language 事务控制语言(对数据库进行控制型事务性操作,命令:commit rollback等  )

添加约束详情操作:mysql数据库约束的使用方法_MySQL数据库约束与列操作_曼仔呀的博客-CSDN博客

数据定义语言 DDL

Data Definition Language

命令:create alter drop

创建数据库并进行调整

create database xxxxx; -- 创建数据库
​
create database xxxx character set xxx; -- 创建指定字符集数据库
​
alter database xxxx character set xxx;  -- 修改某一数据库字符集
​
drop database xxxx;-- 删除某一数据库
​
use  xxxx; -- 使用某一数据库
​
select database(); -- 查询正在使用的数据库
​
show databases; -- 展示数据库
​
show create database xxxx; -- 展示创建的某一数据库

数据类型

数据类型说明
int整数,
double小数,double(3,1) 可输入 :12.1
date日期,年月日
datetime精准日期,年月日时分秒
timestamp时间戳
varchar可改变字符,varchar(10)十个长度内改动
char不可改变字符,char(10) 无论怎么填写内容都只有十个长度

创建数据表

创建create

改动 alter

剔除 drop

-- 在数据库中创建名为 exmple 的数据表并进行如下定义
create table exmple(
  num int,
  name varchar(10),
  sex char(1),
  birthday date,
  point double(4,2)
);
-- 增加一列                            alter table 表名 add 新增列名和类型
alter table exmple add age varchar(4);
​
-- 修改某一列的类型                     alter table 表名 modify 该列名和新类型
alter table exmple modify sex char(2);
​
-- 修改某列的名称与类型                 alter table 表名 change 旧列名 新列名和新类型
alter table exmple change point id char(18);
​
-- 删除某一列                          alter table 表名 drop 要删除的列名
alter table exmple drop sex;
​
-- 修改数据表的字符集                  alter table 表名 charset 编码方式
alter table exmple charset gbk;
​
-- 修改数据表的名称                    rename table 旧表名 to 新表名
rename table exmple to exmple2;--易错
​
-- 删除数据表                          drop table 表名(if exists 表名)
drop table exmple;                  
drop table if exists exmple; -- if exists
​
-- 展示数据表 包含字符集                    show create table 表名
show create table exmple;     --易混淆
​
-- 查询数据表的结构                      desc 表名
desc exmple;                  --易混淆

施加约束

添加规则以用来规定,限制。限制表中的内容,确保数据库满足业务规则。

约束类型

约束命令内容
primary key添加主键约束,使内容在表中唯一且非空
not null使内容非空
unique使内容唯一,不能重复,但可为空
auto_increment逐渐递增,每次增加1 ,设置属性的列必须为主键
foreign key设置外键,只能引用外表中的列的值或使用空值。

示例:

-- 自增器起始值为1,可以手动指定
alter table 表名 auto_increment=起始值;
-- 创建完表后,添加主键
alter TABLE 表名 add primary key(id);  
create table exmple(
    id int primary key auto_increment comment '设置id 为整数列 添加主键元素,并自动增长',
    name varchar(10) unique comment '设置name 添加唯一约束',
    gender char(1) not null comment '设置gender 不能为空'
);
​
-- 取消表的主键和自增长
ALTER TABLE exmple MODIFY id int;     --取消自增 必须先进行
ALTER TABLE exmple DROP PRIMARY key;             --取消主键  在这之前必须先取消自增,因为自增是主键才能有的属性
ALTER TABLE exmple MODIFY id int NOT NULL FIRST,DROP PRIMARY key; -- 或者一次性全部取消

创建表添加注释

comment'xxxxxx'  -- 添加注释
create table employee(
    id int primary key auto_increment comment '编号',
    name varchar(20) not null unique comment '姓名', 
    gender varchar(10) comment '性别',
    birthday date comment '生日',
    entry_date date comment '入职日期',
    job varchar(30) comment '工作',
    salary double not null comment '薪水'
);

复合主键

在设置一列为一个键时,如果无法确定为唯一一行,就用两列或者更多列组合,确定唯一一行

create table `student` (
  `id` int(11) not null auto_increment,
  `name` varchar(20) not null,
  `age` int(11) default null,
  primary key  (`id`,`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

数据操作语言 DML

Data Manipulation Language

命令:insert、delete、update等

添加数据 insert

语法:

-- 公式
insert into 表名(列名1,列名2,...列名n) values(值1,值2,...值n); 
​
​
-- 一一对应
insert into xxx (id,name,gender,salary) values(1,'tom','男',2000);
​
​
-- 省略主键
insert into xxx (name,gender,salary) values('jerry','男',3000);
​
​
-- 指定字段
insert into xxx (name,salary) values('rose',6000);
​
​
-- 省略字段时,类型里的数据必须全写
insert into xxx values (null,'jack','男',7000);
        
        -- varchar、char等 添加字符串需加引号
         
         
-- 批量添加数据
insert into xxx values
(1,'aaa','男',5000),
(2,'bbb','女',6000),
(null,'ccc','男',null); -- 数据组用逗号隔开
​
​
-- 将一个查询的结果数据插入到一个表 ,大数据中,基本只使用这种方式进行数据的插入
insert into xxx 
select * from xxx;

删除数据 delete

删除 行

语法:

delete from xxx (where 条件); -- 公式
delete from xxx where id=1;  -- 删除id为1 的一行数据
delete from xxx where gender = '男'; -- 删除性别为 “男” 的若干行数据

注:

-- 不添加指定条件,则删除表中所有数据
delete from xxx;

truncate 删除

delete from xxx;     -- 对每一条数据都执行一次删除操作
truncate table xxx;   -- 先删除整张表,然后再创建一张新的、相同的表 (效率较高)

修改数据 update

update xxx set 列名1 = 值1 , 列名2 = 值2 , …… (where 条件);-- 公式
​
update xxx set gender = '女'  where name ='tom'; -- 修改tom的性别为女
​
update xxx set gender = '女' ,salary = 10000 where name = 'tom';
-- 修改tom的性别为女,并工资改为10000
​
update xxx set gender = '女';  -- 修改所有人的性别为女
​
update xxx set salary = salary + 2000 where name = 'tom';
-- 把tom的薪水在原有基础上+2000

注: 如果不加任何条件,则会将表中所有记录全部修改。

数据查询语言 DQL

Data Query Language

查询完整语法

select
    字段列表
from
    表名列表
where
    条件列表
group by
    分组字段
having
    分组之后的条件
order by
    排序
limit
    分页限定

select特点

* select 可以查询 表中的字段 表达式  常量值  函数
* 查询出的结果是一个虚拟表 不影响实际表中的数据

简单查询

==查询所有记录==

语法:

SELECT * FROM 表名; 如果用cmd查询出来的数据为乱码,使用 set names GBK

示例:

-- 创建表
create table stu(
	id int,
	name varchar(20),
	chinese double,
	english double,
	math double
);
-- 插入记录
insert into stu(id,name,chinese,english,math) values(1,'tom',89,78,90);
insert into stu(id,name,chinese,english,math) values(2,'jack',67,98,56);
insert into stu(id,name,chinese,english,math) values(3,'jerry',87,78,77);
insert into stu(id,name,chinese,english,math) values(4,'lucy',88,NULL,90);
insert into stu(id,name,chinese,english,math) values(5,'james',82,84,77);
insert into stu(id,name,chinese,english,math) values(6,'jack',55,85,45);
insert into stu(id,name,chinese,english,math) values(7,'tom',89,65,30);
==查询表中所有学生的姓名和对应的语文成绩==

语法:
	SELECT 字段名1,字段名2... FROM 表名;
举例:
-- 查询所有
select * from stu;

-- 查看班里有哪些人的名字
select name from stu;

select math from stu;

-- 查看表中学生对应的数学成绩
select name,math from stu;

-- 查看jack的所有成绩
select * from stu where name = 'jack'

-- 查看english为78  学生姓名
select id,name,english from stu where english = 78

-- 给所有学生数据成绩加10分
select id , name , math + 10 from stu;

去重复

语法:
	select distinct 字段名1,字段名2... FROM 表名;
举例:
	-- 去重复
	SELECT distinct name FROM stu;
	
	-- 可以去重复多个字段, 但两个字段都重复才会去重复
	SELECT distinct name, chinese FROM stu; 

Ifnull

==统计每个学生的总分==

SELECT name, chinese + english + math FROM stu;

注: 在做行运算时,null参与的运算,计算结果都为null

使用ifnull(参数1,参数2) 

如果参数1有值,就走参数1 ,如果参数1为null,就走参数2

SELECT name, chinese + ifnull(english,0) + math FROM stu;

总结

* 在做行运算时,null参与的运算,计算结果都为null  
SELECT '123' + 100; -- 223 如果能转换成整数就跟后面的数值进行相加
SELECT 'abc' + 100; -- 100 如果不能转换成整数 转换为0 在跟后面的数值进行相加

别名

关键字 as

as : as可以省略 ,引号也可省略,给表取别名时不可用引号
1. 可以用在某个字段上   name as 姓名
2. 可以用在函数上      min(sarlay) as 最低工资
3. 可以用在表上        from sutdent as s

注意事项: 如果给表起了别名,后面在使用的时候,必须要用别名

条件查询

语法

SELECT 字段名 FROM 表名 [WHERE 条件];

运算符

运算符说明
> 、< 、<= 、>= 、= 、<> !=<>在 SQL 中表示不等于,在 mysql 中也可以使用!= 没有==
BETWEEN...AND在一个范围之内
IN( 集合)集合表示多个值,使用逗号分隔
IS NULL 不为空 is not null查询某一列为 NULL 的值,注:不能写=NULL
LIKE模糊查询 占位符: _:单个任意字符 %:多个任意字符
AND 或 &&与,SQL 中建议使用前者,后者并不通用。
OR 或 ||
NOT 或 !

示例:

-- 创建表
CREATE TABLE stu1 (
  id int,
  name varchar(20),
  age int,
  sex varchar(5),
  address varchar(100),
  math int,
  english int
);
-- 插入记录
INSERT INTO stu1(id,NAME,age,sex,address,math,english) VALUES 
(1,'马云',55,'男','杭州',66,78),
(2,'马化腾',45,'女','深圳',98,87),
(3,'马景涛',55,'男','香港',56,77),
(4,'柳岩',20,'女','湖南',76,65),
(5,'柳青',20,'男','湖南',86,NULL),
(6,'刘德华',57,'男','香港',99,99),
(7,'马德',22,'女','香港',99,99),
(8,'德玛西亚',18,'男','南京',56,65);
-- 查询math分数大于80分的学生
SELECT * FROM student2 WHERE math > 80;

-- 查询english分数小于或等于80分的学生
SELECT * FROM student2 WHERE english <= 80;

-- 查询age等于20岁的学生
SELECT * FROM student2 WHERE age = 20;

-- 查询age不等于20岁的学生
SELECT * FROM student2 WHERE age != 20;

--查询age大于35且性别为男的学生(两个条件同时满足)
SELECT * FROM student2 WHERE age > 35 AND sex = '男';

--查询age大于35或性别为男的学生(两个条件其中一个满足)
SELECT * FROM student2 WHERE age > 35 OR sex = '男';

--查询id是1或3或5的学生
SELECT * FROM student2 WHERE id = 1 OR id =3 OR id = 5;

SELECT * FROM student2 WHERE id IN(1,3,5);   -- in关键字 ,查询id是1或3或5的学生

--查询id不是1或3或5的学生
SELECT * FROM student2 WHERE id NOT IN(1,3,5);

--查询english成绩大于等于77,且小于等于87的学生
SELECT * FROM student2 WHERE english >=77 AND english <=87;

SELECT * FROM student2 WHERE english BETWEEN 77 AND 87;

--查询英语成绩为null或不为null的学生
SELECT * FROM student2 WHERE english IS NULL;
SELECT * FROM student2 WHERE english IS NOT NULL;

--查询姓马的学生
SELECT * FROM student2 WHERE name LIKE '马%'; --  %表示任意长度的字符

--查询姓不为马,但名中包含'马'字的学生
SELECT * FROM student2 WHERE name LIKE '_%马%';

--查询姓马,且姓名有三个字的学生
SELECT * FROM student2 WHERE name LIKE '马__';  --  _表示1个字符

--where 1 = 1 为了拼接后面要过滤的条件,如果没有条件就查询所有,如果有条件就依据条件查询
select * from stu1 where 1=1 ;

select * from stu1 where 1=1 and address = '杭州';

高级查询

排序查询

SELECT 字段名 FROM 表名 [WHERE条件] ORDER BY 字段名 [ASC|DESC];

ASC: 升序,默认值

DESC: 降序

注: 如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件。

聚合(集)函数

概述

在sql中函数主要要对数据进行处理。函数可以把经常使用的代码封装起来,需要的时候直接调用即可。这样既提高了编写代码的效率,又提高了可维护性。

常用函数类型
  • 算术函数

  • 字符串函数

  • 日期函数

  • 转换函数

  • 聚合函数/聚集函数

函数sql语法
SELECT 聚合函数(列名) FROM 表名;
常见聚合函数
聚合函数说明
count(*) | count(主键)计算表中的总记录数
max计算最大值
min计算最小值
sum计算和
avg计算平均值
  • 注意:==聚合函数的计算,排除null值。==

  • 解决方案

    1. ==选择不包含非空的列进行计算==

    2. ==IFNULL函数==

示例:

-- 查询学生总数
SELECT COUNT(*) FROM stu;
select count(1) from stu;-- sql优化方案 count(1)效率高

-- 查询年龄大于40的总数
SELECT COUNT(*) FROM stu WHERE age >40;

-- 查询数学成绩总分 平均分
SELECT SUM(math) FROM stu;
SELECT AVG(math) FROM stu;

-- 查询数学成绩最高分 最低分
SELECT MAX(math) FROM stu;
SELECT MIN(math) FROM stu;

-- 查看最高分的人, 通过子条件查询(把一个sql的结果当作另一个sql的条件来用)
select id ,name ,math from stu where math = (select max(math) from stu);
其它函数
函数名说明作用
length(str)字符函数获取字符的字节个数
upper(str)字符函数将字符转换为大写字符
lower(str)字符函数将字符转换为小写字符
substring(str,pos)字符函数截取从指定索引处后面所有的字符
substring(str,pos,len)字符函数截取从pos索引开始截取len个字符
substring_index(str, delimiter, count)字符函数从字符串中提取指定分隔符的子字符串,delimiter:用于分隔的字符串。 count:要提取的子字符串的个数,正数,从左侧开始提取,负数,从右侧开始
replace(str,from_str,to_str)字符函数将str中的字符 from_str字符替换成to_str字符
round(x)数学函数四舍五入
round(x,d)数学函数四舍五入 d:代表的是保留小数点后几位
ceil(x)数学函数向上取整
floor(x)数学函数向下取整
mod(n,m)数学函数取余数 mod(10,3) 相当于: select 10 % 3
sqrt(x)数学函数求平方根
POWER(a,b)数学函数求a的b次幂
LOG(x)数学函数求以e为底的自然对数
LOG(x, base)数学函数求以指定底数为底的对数
EXP(x)数学函数求e的x次方。
SIN(角度值)COS()TAN()数学函数三角函数
str_to_date(str,format)日期函数将日期字符转换成指定格式的日期 str_to_date('1990-11-11','%Y-%m-%d');
date_format(date,format)日期函数将日期转换成字符串 date_format(now(),'%Y/%m/%d');

format格式

DATE_FORMAT字符串格式格式化日期
%Y/%m/%d2022/04/26
%Y-%m-%d2022-04-26
%e/%c/%Y4/8/2022
%d/%m/%Y %H:%i26/04/2022 17:27
%b %d %Y %h:%i %pApr 26 2022 05:28 PM
%Y-%m-%d %T:%f2022-04-26 17:29:30:000000
%W %D %M %Y %TTuesday 26th April 2022 17:31:34

 format样式整理:

   年:%Y  显示四位 : 2015            %y 只显示后两位  :15

   月: %M 月份的英文显示:October  %m 月份的阿拉伯显示:01-12  %b 月份的英文缩略显示:Oct           
        %c 月份的阿拉伯显示:1-12

   日:  %d 阿拉伯显示:00-31        %D 带有英文后缀:1st-31th     %e 阿拉伯显示:1-31          
         %j   年的天:001-366   

   时:   %H :00-23           %h:01-12        %I:01-12      %k:0-23      %l:1-12

   分:   %i:00-59

   秒:   %S:00-59        %s:00-59

   微秒: %f

   AM/PM: %p

   12小时制时间: %r:   02:02:44 PM

   24小时制时间: %T:  14:02:44

   周: %W:周的英文显示      %w 周的阿拉伯显示 :0(星期日)-6(星期六)  
        %a   周的英文缩略显示:Mon-


-- 在GBK 编码下,1个中文字符占2个字节,所以总字节长度2
-- 在UTF-8 编码下,1个中文字符占3个字节,所以总字节长度3
    select length('码农'); -- 获取长度
    select length('abc'); 
    select upper('abc'); 
    select lower('ABC');
    select ceil(3.4);
    select floor(3.4);
    select round(5.5);
    select md5('123abc');
    select str_to_date('2022/01/02', '%Y/%m/%d'); -- 2022-01-02

分组查询

对一列数据进行分组,相同的内容分为一组,通常与聚合函数一起使用,完成统计工作

SELECT 字段 1,字段 2... FROM 表名 [where条件] GROUP BY 分组字段 [HAVING 条件] [order by];

  • ==注意事项==

    • 分组之后查询的字段:分组字段、聚合函数

    • wherehaving的区别?

      • where分组之前进行过滤。having在分组之后进行过滤。

      • where 后不可以跟聚合函数,having可以进行聚合函数

      • having 不能脱离 group by ,如果脱离group by 不能直接使用,一般与group by 一块使用

      • 换句话说,WHERE子句用于过滤行,而HAVING子句用于过滤组

    • where: 操作的数据源: 原始表

    • having: 操作的数据源: 结果集

分页查询

SELECT * 字段列表 [as 别名] FROM 表名 [WHERE 子句] [GROUP BY 子句][HAVING 子句][ORDER BY 子句][LIMIT 子句];
LIMIT offset,length;
  • offset:起始行数,从 0 开始计数,如果省略,默认就是 0

  • length:显示的条数

开始的索引 = (当前的页码 - 1) * 每页显示的条数

-- 每页查询显示3条数据
-- 开始行数 = (当前页 - 1) * 要显示的条数
--     0     =  (1 - 1)* 3
--     3     =  (2 - 1)* 3
--     6     =  (3 - 1)* 3
SELECT * FROM stu LIMIT 0,3; -- 第1页
SELECT * FROM stu LIMIT 3,3; -- 第2页
SELECT * FROM stu LIMIT 6,3; -- 第3页

多表操作

一对一

 

一对多 

多对多

外键约束

限定二张表有关系的数据,保证数据的正确性、有效性和完整性

create table 表名(
  	列名 数据类型 约束名,
    列名 数据类型 约束名,
  	[constraint] [约束名] foreign key(外键列) references 主表(主键)
);	
已有表添加外键
alter table 表名 add [constraint] [约束名] foreign key(外键列) references 主表(主键);
删除外键约束
alter table 表名 drop foreign key 约束名;
sql查看外键约束
SELECT
    CONSTRAINT_NAME
FROM
    INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
    REFERENCED_TABLE_NAME = '被引用表名'
    AND TABLE_NAME = '引用表名'
    AND REFERENCED_COLUMN_NAME = '被引用表的列名';

示例

-- 创建部门表
-- 一方,主表
CREATE TABLE dept(
	d_id INT PRIMARY KEY AUTO_INCREMENT,
	d_name VARCHAR(20),
	d_location VARCHAR(20)
);

-- 创建员工表
-- 多方,从表
CREATE TABLE emp(
	e_id INT PRIMARY KEY AUTO_INCREMENT,
	e_name VARCHAR(20),
	e_age INT,
	d_id INT, -- 外键对应主表的主键
	-- CONSTRAINT emp_ibfk_1  可以省略不写
	-- CONSTRAINT `emp_ibfk_1` FOREIGN KEY (`d_id`) REFERENCES `dept` (`d_id`)
    FOREIGN KEY (`d_id`) REFERENCES `dept` (`d_id`)
);
造成笛卡尔积的情况

如果不加过滤条件,a表中的每一条记录,都和b表中的每一条进行匹配连接。 会造数据量级的增长,如果在大数据中,这种情况是灾难性的,避免该情况发生。

SELECT * FROM emp ,dept;

-- 如果要得到正确的数据,需要添加过滤条件
select * from a,b where a.a_id = b.a_id;

注:

1) 主表不能删除从表已引用的数据
2) 从表不能添加主表未拥有的数据
3) 先添加主表数据再添加从表数据
4) 先删除从表数据再删除主表数据
5) 外键约束允许为空但不能是错的

== 主外键关系: 注意事项 ==
-- 前者:建立【实际的主外键关系】 和 后者:建立【逻辑主外键关系】 的区别?
-- 前者有约束,必须按照外键约束来写
-- 后者没有外键约束,但你不能写主键不存在
-- 前者删除受主外键约束,后者删除不再受主外键约束
-- 前者可能会造成级联删除, 后者不会造成级联删除

在实际开发中,一般不建立实际的外键关系,而是建立逻辑外键关系 在互联网公司中,不建立实际的外键关系,在实际传统行业中,需要建立实际的外键关系

多表查询

笛卡尔积,是指集合A中元素与B中元素所有的两两组合。

内链接查询

必须表与表之间的关系一一对应

隐式内连接查询

Implicit Inner Join

select * from a,b where a.a_id = b.a_id;  

没有INNER JOIN,形成的中间表为两个表的笛卡尔积,需要使用条件保留有意义的数据

-- 查询老师对应的课程 结果:必须主外键一一对应
select * from teacher , course where teacher.t_id = course.t_id;
显式内连接查询

Explicit Inner Join

-- 查询老师对应的课程 结果:必须主外键一一对应
select * from a inner join b on a.a_id = b.a_id  

显示的内连接,一般称为内连接,有INNER JOIN,形成的中间表为两个表经过ON条件过滤后的笛卡尔积,可以省略INNER

-- 查询老师对应的课程
select * from teacher inner join course on teacher.t_id = course.t_id;

外链接查询

左外连接
select * from a left [outer] join b on a.a_id = b.b_id

把left 关键字之前的表,是定义为左侧。 left关键字之后的表,定义右侧。

当两个表连接的时候,如果左侧表有数据,右侧的表没有对应的数据。会把左侧的表中的数据显示出来。

示例:

select * from teacher left join course on teacher.t_id = course.t_id;
右外连接
select * from a  right [outer] join b on a.a_id = b.b_id

right之前的是左侧,right之后的是右侧。

当两个表连接的时候,如果右侧表有数据,左侧的表没有对应的数据。会把右侧的表中的数据显示出来

select * from teacher right join course on teacher.t_id = course.t_id;
全外连接

把两侧的内容都显示出来

-- union 是把两个查询的结果进行合并。 去掉重复的合并

select * from teacher left join course on teacher.t_id = course.t_id 
union
select * from teacher right join course on teacher.t_id = course.t_id;


-- union all 把两个结果集都显示出来,不会合并去重复

select * from teacher left join course on teacher.t_id = course.t_id 
union all
select * from teacher right join course on teacher.t_id = course.t_id;


-- mysql 不支持 full 关键字 全外连接。
select * from a full join b on a.a_id = b.a_id 

关联子查询

关联子查询:将一个查询结果当作另一个查询的条件部分(可以是表,也可以是过滤元素)

数据控制语言 DCL

用户权限

创建用户

create user '用户名'@'主机名' identified by '密码';

主机名:限定客户端登录ip 指定ip:127.0.0.1 (localhost) 任意ip:%

例如:

create user 'temp'@'%' identified by '123';

删除用户

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

查看权限

show grants for '用户名'@'主机名';

例如:

show grants for 'temp'@'%';

授于权限

grant 权限1, 权限2 ,…… on 数据库名.表名 to '用户名'@'主机名' ;

例如:

grant select , update , … on test.temp to 'temp'@'%' ;
-- 授予权限后,需刷新权限
flush privileges;

授于全部-指定的库和表

-- 授于整个test 库的权限
-- jack 这个用户对所有库下的所有表有操作权限
grant all on *.* to 'jack'@'%' ;

-- 刷新权限
flush privileges;

撤销授权

revoke 权限1 , 权限2 , …… on 数据库名.表名 from '用户名'@'主机名';

例如:

-- 撤销删除权限
revoke delete on test.temp from 'temp'@'%' ;
-- 撤销全部权限
revoke all on *.* from 'temp'@'%' ;

密码管理

普通用户
set password = password('密码')

-- 加密函数
SELECT PASSWORD('123');
select md5('123')
管理员
-- 登录mysql
mysql -uroot -proot

-- 切换mysql默认的数据库【mysql】
use mysql;

-- 修改mysql服务器中自带的mysql数据库的user表下有一个authentication_string修改即可
update user set authentication_string =password('abc') where user='root';  

-- 或者使用 set 命令修改密码
set password for 'temp'@'%' = password('132'); -- 修改之后需要重启服务器

三大范式

数据库第一范式

指设计数据表时,要实现功能详尽,即必须明确字段

数据库第二范式

指设计数据表时,数据表要功能集聚,一张表只负责一块内容,即在第一范式的基础上,明确每一张表

数据库第三范式

指设计数据表时,尽可能在减少表之间依赖 ,减少耦合 的情况下建立连接,即在第一范式和第二范式的基础上,让表与表之间建立关系

索引

提高查询的效率

-- 创建索引
create index 索引名 on 表名(字段名)

--查看索引
show index from 表名

-- 删除索引
drop index from 表名

横表/纵表(重要)

横表就是普通的建表方式,表结构为:主键、字段1、字段2、字段3...
纵表表结构为: 主键、字段代码、字段值。字段代码为字段1、字段2、字段3...。  

横表

优点:一行表示了一个实体记录,清晰可见,一目了然。 缺点:如果现在要给这个表加一个字段,那么就必须重建表结构。

纵表

优点:如果现在要给这个表加一个字段,只需要添加一些记录。 缺点:数据描述不是很清晰,而且会造成数据库数据很多。另如果需要分组统计,要先group by,较繁琐。

总结:把不容易改动表结构的设计成横表, 把容易经常改动不确定的表结构设计成纵表。

横表转纵表

把字段变内容

先创建横表

create table school_report (
   student_name varchar(20),
   chinese varchar(20),
   math varchar(20),
   english varchar(20)
);

INSERT INTO `school_report`(`student_name`, `chinese`, `math`, `english`) VALUES ('张三', '67', '78', NULL);
INSERT INTO `school_report`(`student_name`, `chinese`, `math`, `english`) VALUES ('李四', '90', NULL, '89');

横表转为纵表
select s.student_name,'chinese' as 科目,s.chinese as 成绩 from school_report s
union all 
select s.student_name,'math' as 科目,s.math as 成绩 from school_report s
union all 
select s.student_name,'english' as 科目,s.english as 成绩 from school_report s;

纵表转横表

把内容变字段

先创建纵表

create table proper(
   student_name varchar(20),
   course_name varchar(20),
   score double
);

INSERT INTO `proper`(`student_name`, `course_name`, `score`) VALUES ('张三', '语文', 67);
INSERT INTO `proper`(`student_name`, `course_name`, `score`) VALUES ('张三', '数学', 78);
INSERT INTO `proper`(`student_name`, `course_name`, `score`) VALUES ('李四', '语文', 90);
INSERT INTO `proper`(`student_name`, `course_name`, `score`) VALUES ('李四', '英语', 89);

纵表转为横表

select 
-- 第一列显示的字段
p.student_name,
-- 当course_name的名字是‘语文’,把对应的成绩显示       sum (case 键  when 字段值 then 字段值关系字段 end)
sum(case p.course_name when '语文' then p.score end ) as 语文, 
sum(case p.course_name when '数学' then p.score end ) as 数学, 
sum(case p.course_name when '英语' then p.score end ) as 英语
from proper p 
-- 对名字进行分组
group by p.student_name

​​​​​​​

数据库备份

把数据库里面的内容进行备份放到硬盘或者其他位置。如果数据库出现问题之后,可以进行数据的恢复

备份数据库

在命令行中  mysqldump -u 用户名 -p 数据库名 > 文件名.sql

-- 进行数据库备份,注:备份命令最后不能加分号 结束
mysqldump -u root -p abc > D://abc.sql

恢复数据库

需要查看备份的sql脚本中没有创建数据库的sql,如果没有该sql,只有表相关的sql,则数据库必须提前存在

第一种恢复:
​​​​​​​-- 继续用windows窗口
mysql -u root -p 数据库名 < D://数据库名.sql

-- 示例
-- 创建一个数据库
create database abc;

-- 切换数据库
use abc;

-- 进行恢复 注意事项:恢复命令不能以 分号结尾
mysql -u root -p abc < D://abc.sql

第二种恢复:

-- 创建一个数据库
create database abc;

-- 切换数据库
use abc;

-- 进行恢复 注意事项:恢复命令不能以分号结尾
source D://abc.sql

-- 查看当前使用的数据库
select database();

-- 查看当前数据库下的所有表
show tables;

记录最后修改时间

添加字段 lasttime 使用timestamp 类型 选择 is not null

悲观锁与乐观锁

如果并发量大,冲突几率高,使用悲观锁,否则使用乐观锁

悲观锁

总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改),所以每次在获取资源操作的时候都会上锁,这样其他线程想拿到这个资源就会阻塞直到锁被上一个持有者释放。也就是说,共享资源每次只给一个线程使用,其它线程阻塞,当前线程用完后再把资源转让给其它线程

乐观锁

总是假设最好的情况,认为共享资源每次被访问的时候不会出现问题,线程可以不停地执行,无需加锁也无需等待,只是在提交修改的时候去验证对应的资源(也就是数据)是否被其它线程修改了(具体方法可以使用版本号机制或 CAS 算法)。

悲观锁施加

-- 悲观锁施加

在数据查询的时候,加上 for update。 -- + where条件就是行级锁 不+就是表级锁

具体步骤:

1.开启事务

begin; / begin work; / start transaction; (三者选一即可)

2.查询某表数据(id为主键)

select * from 表名 where id = 1 for update; 

3.修改表数据

update 表名 set 表字段 = xxx;

4.提交事务

commit; / commit work; (二选一即可)

关于for update的注意事项:

  1. 如果不开启事务,for update是不会锁任何东西的。

  2. 开启事务后,where条件字段是索引字段的话,该锁为行锁,如果不是索引字段,则为表锁。

  3. for update 是写锁,该操作不会影响读操作。

两个常见问题

mysql使用事务前,需要关闭自动提交(set autocommit=0;)吗?

不需要。mysql 使用事务功能是不需要手动关闭自动提交的,只要 start transaction 开启了事务,自动提交就会被自动关闭,然后在使用 commit 之后,又会被重新打开。

for update 会锁住读操作?

正常的读操作是不会受到影响。当执行 select * from 表名 where id=1 for update; 后,在另外的事务中如果再次执行select * from 表名 where id=1 for update; 则第二个事务会一直等待第一个事务的提交,此时第二个查询处于阻塞的状态。如果 是在第二个事务中执行select * from 表名 where id=1;则能正常查询出数据,不会受第一个事务的影响。

mysql引擎

Innodb引擎

事务:逻辑上一组操作,要么同时成功,要么同时失败

InnoDB是MySQL5.5.x开始默认的事务型引擎,也是使用最广泛的存储引擎。被设计用来处理大量短期事务的。

InnoDB所有的表都保存在同一个数据文件中(也可能是多个文件,或者是独立的表空间文件),表的大小只受限于操作系统文件的大小。表的结构定义存在.frm后缀文件中,数据和索引集中存放在.idb后缀文件中。因为表数据和索引是在同一个文件,InnoDB的索引是聚簇索引。

InnoDB采用MVCC支持高并发,并且实现了四种标准的隔离级别(读未提交,读已提交,可重复读,可串行化),其默认级别是REPEATABLE-READ(可重复读),并且通过间隙锁(next-key locking)策略防止幻读的出现。间隙锁不仅仅锁定查询涉及的行,还会对索引中的间隙行进行锁定,以防止幻影行的插入。

InnoDB表是基于聚簇索引建立的,聚簇索引对主键的查询有很高的性能。但是InnoDB的非主键索引中必须包含主键列,所以如果主键列很大的话,非主键索引也会很大。如果一张表的索引较多,主键应该尽可能的小。关于索引,后面会详细讲解。

InnoDB的内部优化,包括磁盘预读(从磁盘读取数据时采用可预测性读取),自适应哈希(自动在内存中创建hash索引以加速读操作)以及能够加速插入操作的插入缓冲区。

MyIASM引擎

在MySQL5.1及之前的版本,MyISAM是默认的存储引擎。提供了大量的特性,包括全文索引,压缩,空间函数等,但是不支持事务和行级锁,而且有一个严重的问题是奔溃后无法安全恢复。

MyISAM的数据表存储在磁盘上是3个文件,表结构定义存在.frm后缀文件中,表数据存储在.MYD后缀文件中,表索引存储在.MYI后缀文件中。表数据和表索引在不同的文件中,所以MyISAM索引是非聚簇索引。而且MyISAM可以存储表数据的总行数。

MyISAM表支持数据压缩,对于表创建后并导入数据以后,不需要修改操作,可以采用MyISAM压缩表。压缩命令:myisampack,压缩表可以极大的减少磁盘空间占用,因此也可以减少磁盘I/O,提高查询性能。而且压缩表中的数据是单行压缩,所以单行读取是不需要解压整个表。

二者区别

1. InnoDB 支持事务,MyISAM 不支持,对于 InnoDB 每一条 SQL 语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条 SQL 语言放在begin 和 commit 之间,组成一个事务;

2. InnoDB 是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。

MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。

3. InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而 MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;

4. Innodb 不支持全文索引,而 MyISAM 支持全文索引,查询效率上 MyISAM要高;

主要的区别:

1、MyIASM是非事务安全的,而InnoDB是事务安全的
2、MyIASM仅支持表级锁,而InnoDB支持行级锁
3. MyISAM 不支持外键,而InnoDB 支持外键
4、MyIASM支持全文类型索引,而InnoDB不支持全文索引
5、MyIASM相对简单,效率上要优于InnoDB,小型应用可以考虑使用MyIASM
6、MyIASM表保存成文件形式,跨平台使用更加方便

主要选择:

1、如果需要支持事务,选择InnoDB,不需要事务则选择MyISAM。

2、如果大部分表操作都是查询,选择MyISAM,如果读写频繁选InnoDB。

3、如果系统崩溃导致数据难以恢复,MyISAM 恢复起来更困难,且成本高。

4.如果不知道用什么,那就用 InnoDB (MySQL5.5 版本开始 Innodb 已经成为 Mysql 的默认引擎(之前是MyISAM),说明其优势是有目共睹的)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值