Mysql的安装、语法、优化

news2024/11/27 8:30:52

1 数据库

数据库是存储数据,管理数据的仓库。

常见的数据库有两种

关系型数据库:数据关系紧密。关系模型是二维表格模型,一个关系型数据库就是由二维表及其之间的关系组成的一个数据集合

Oracle、MySQL、SQLServer、Access

非关系型数据库:数据关系松散。有:

MongoDB、Redis、Solr、ElasticSearch、Hive、HBase

2 MySql的安装

1)版本mysql-5.5.27-winx64.msi

2)Mysql数据库默认的编码是latin1等价于iso-8859-1,修改为utf-8

3)用户名和密码统一设置成“root”

3 SQL语句

结构化查询语言

4 字段类型

1 命名规则

1)字段名必须以字母开头,尽量不要使用拼音

2)长度不能超过30个字符(不同数据库,不同版本会有不同)

3)不能使用SQL的保留字,如where,order,group

4)只能使用如下字符a~z、A~Z、0~9、$ 等

5)Oracle习惯全大写:USER_NAME,mysql习惯全小写:user_name

6)多个单词用下划线隔开,而非java语言的驼峰规则

2 字符

1)char:长度固定,不足使用空格填充,最多容纳2000个字符,char(11)存储abc,占11位。查询速度极快浪费空间

2)varchar:变长字符串,最多容纳4000个字符,varchar(11)存储abc,只占3位查询稍慢,但节省空间Oracle为varchar2

3)不同数据库版本长度限制可能会有不同

3 数字

1)int、int(3):oracle不支持,使用number替代

2)numeric(5,2):3位整数,2位小数

3)decimal和numeric等效

4 日期

1)date 包含年月日

2)datetime 包含年月日和时分秒

3)timestamp 时间戳,不是日期,而是从1970年1月1日到指定日期的毫秒数

5 大文本

大量文字(不推荐使用,尽量使用varchar替代)。

以utf8编码计算的话,一个汉字在占3个字节

1)LANGTEXT:1431655765个汉字,14亿。存储空间占用:4G的数据

2)MEDIUMTEXT:5592405个汉字,560万。存储空间占用:16M的数据

3)TEXT:21845个汉字,约20000。存储空间占用:64K的数据

6图片

1)blob 二进制数据,可以存放图片、声音,容量4g

2)缺点明显,数据库庞大,备份缓慢

3)目前主流只存储其访问路径,文件则存放在磁盘上

5表操作

1创建库

#创建数据库,设置字符集u8,防止中文乱码,注意下面的`刀秋不是单撇哦

CREATE DATABASE `mysql-db` DEFAULT CHARSET=utf8;

2创建表

#学生表

CREATE TABLE student(

id INT(4), #学号

NAME VARCHAR(20), #姓名

sex CHAR(2), #性别

birthday DATE, #出生日期

salary NUMERIC(7,2), #奖学金

PRIMARY KEY(id) #主键,记录唯一标识

);

#查看表结构

DESC student;

注意

1)SQL可以写成一行中间无需换行

2)SQL不区分大小写,oracle中习惯表名字段名都大写,mysql中习惯小写

3 修改表

不是重点,一般都使用可视化方式修改,了解即可

#添加字段

ALTER TABLE student ADD(classid INT);

#修改字段长度

ALTER TABLE student MODIFY COLUMN NAME VARCHAR(30);

#注意长度不能小于已有的数据长度,否则会被永久破坏,不可修复

#删除字段

ALTER TABLE student DROP COLUMN classid;

#修改表名

RENAME TABLE student TO tb_student;

RENAME TABLE tb_student TO student;

4删除表

#删除表

DROP TABLE student;

删除表,数据都自动被删除,数据将永久性丢失

6 数据操作 CRUD

1新增

#不声明字段,顺序必须和表的一致

INSERT INTO student VALUES(1,'陈子枢','男','1988-10-11',3000);

#声明全部字段,顺序可以不一致,推荐方式

INSERT INTO student (id,NAME,sex,salary,birthday)

VALUES(2,'陈晨','女',30000,'2020-02-02');

#声明部分字段,没有的字段默认值null

INSERT INTO student (id,NAME) VALUES(3,'王涛');

2修改

#修改一个字段,必须设置where条件

UPDATE student SET sex='女' WHERE id=1;

#修改某个字段设置为null

UPDATE student SET NAME=NULL WHERE id=3;

#删库跑路蹲局子

UPDATE student SET NAME='我爸是李刚';修改了所有数据

如何预防这种行为?一般在企业中开发者会有测试数据库,不会直接连接生产环境的数据库

3删除

#删除一条记录,必须有where条件

DELETE FROM student WHERE id=3;

#删除所有数据

DELETE FROM student;

4查询

#查询所有数据

SELECT * FROM student;

#id为1的记录

SELECT * FROM student WHERE id=1;

7 约束 constraints

1 非空约束 not null

DROP TABLE IF EXISTS tb_user;  #如果表存在则删除,慎用会丢失数据

CREATE TABLE tb_user(

  id INT AUTO_INCREMENT,

  NAME VARCHAR(30) UNIQUE NOT NULL,

  age INT,

  phone VARCHAR(20) UNIQUE NOT NULL,

  email VARCHAR(30) UNIQUE NOT NULL,

  PRIMARY KEY (id)

);

DESC tb_user;

#id为自增主键,null值无效,数据库会自动用下一个id值替代

#age因为运行为null,所以可以设置为null

INSERT INTO tb_user (id,age) VALUES(NULL,NULL);

2 唯一约束 unique

Name字段创建了唯一约束,插入数据时数据库会进行检查,如果插入的值相同,就会检查报错

DROP TABLE IF EXISTS tb_user;  #如果表存在则删除,慎用会丢失数据

CREATE TABLE tb_user(

  id INT,

  NAME VARCHAR(30) UNIQUE NOT NULL,

  phone VARCHAR(20) UNIQUE NOT NULL,

  email VARCHAR(30) UNIQUE NOT NULL,

  PRIMARY KEY (id)

);

DESC tb_user;

INSERT INTO tb_user (id,NAME) VALUES(1,'tony');

INSERT INTO tb_user (id,NAME) VALUES(2,'tony');

执行上面语句出错:

Query : INSERT INTO tb_user (id,NAME) VALUES(2,'tony')

Error Code : 1062

Duplicate entry 'tony' for key 'name'

展示表结构:

DESC tb_user;

3 主键约束 primary key

主键是一条记录的唯一标识,具有唯一性,不能重复

DROP TABLE IF EXISTS tb_user;  #如果表存在则删除,慎用会丢失数据

CREATE TABLE tb_user(

  id INT,

  NAME VARCHAR(30),

  PRIMARY KEY (id)

);

INSERT INTO tb_user (id,NAME) VALUES(1,'tony');

INSERT INTO tb_user (id,NAME) VALUES(1,'hellen');

第二句插入就会报错:

Query : INSERT INTO tb_user (id,NAME) VALUES(1,'hellen')

Error Code : 1062

Duplicate entry '1' for key 'PRIMARY'

提示主键1的值已经存在,重复了

4 外键约束 forgrein key

DROP TABLE IF EXISTS tb_user_address;  #如果表存在则删除,慎用会丢失数据

DROP TABLE IF EXISTS tb_user;  #如果表存在则删除,慎用会丢失数据

CREATE TABLE tb_user (

  id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,  #自增主键

  NAME VARCHAR(50) NOT NULL UNIQUE,  #非空,唯一索引

  sex CHAR(2) DEFAULT '男',  #默认值

  phone CHAR(18),

  age INT,

  CHECK (age>0 AND age<=200),

  createdTime DATE DEFAULT NOW()

);

CREATE TABLE tb_user_address (

  user_id INT PRIMARY KEY NOT NULL,

  address VARCHAR(200),

  FOREIGN KEY(user_id) REFERENCES tb_user(id)

);

DESC tb_user;

tb_user_address中user_id字段录入tb_user表不存在的主键值,将报错

5默认约束 default

设置默认值

DROP TABLE IF EXISTS tb_user;  #如果表存在则删除,慎用会丢失数据

CREATE TABLE tb_user (

  id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,  #自增主键

  NAME VARCHAR(50) NOT NULL UNIQUE,  #非空,唯一索引

  sex CHAR(2) DEFAULT '男',  #默认值

  phone CHAR(18),

  age INT,

  createdTime DATE DEFAULT NOW()

);

DESC tb_user;

6检查约束 check

很少使用,了解即可

DROP TABLE IF EXISTS tb_user;  #如果表存在则删除,慎用会丢失数据

CREATE TABLE tb_user (

  id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,  #自增主键

  NAME VARCHAR(50) NOT NULL UNIQUE,  #非空,唯一索引

  sex CHAR(2) DEFAULT '男',  #默认值

  phone CHAR(18),

  age INT,

  CHECK (age>0 AND age<=200),

  createdTime DATE DEFAULT NOW()

);

DESC tb_user;

录入age超过200将报错

8 数据表

使用表来说明Mysql其他功能

1部门表 dept

字段名称

数据类型

是否为空

备注

deptno

int

部门编号,PK主键

dname

varchar(20)

Y

部门名称

loc

varchar(13)

Y

部门所在地点

Mysql:

CREATE TABLE dept(

  deptno NUMERIC(2) NOT NULL,

  dname VARCHAR(14),

  loc VARCHAR(13)

);

INSERT INTO dept VALUES(1,'accounting','一区');

INSERT INTO dept VALUES(2,'research','二区');

INSERT INTO dept VALUES(3,'operations','二区');

2 员工表 emp

字段名称

数据类型

是否为空

备注

empno

int

员工编号,PK主键

ename

varchar(10)

Y

员工名称

job

varchar(10)

Y

职位

mgr

int

Y

上级编号

hiredate

datetime

Y

月工资

sal

decimal(8,2)

Y

奖金

comm

decimal(8,2)

Y

奖金

deptno

int

Y

所属部门 FK外键

Mysql:

CREATE TABLE emp(

  empno NUMERIC(4) NOT NULL,

  ename VARCHAR(10),

  job VARCHAR(9),

  mgr NUMERIC(4),

  hiredate DATE,

  sal NUMERIC(7,2),

  comm NUMERIC(7,2),

  deptno NUMERIC(2)

);

INSERT INTO emp VALUES(100,'jack','副总',NULL,'2002-05-03',90000,NULL,1);

INSERT INTO emp VALUES(200,'tony','总监',100,'2015-02-02',10000,2000,2);

INSERT INTO emp VALUES(300,'hana','经理',200,'2017-02-02',8000,1000,2);

INSERT INTO emp VALUES(400,'leo','员工',300,'2019-02-22',3000,200.12,2);

INSERT INTO emp VALUES(500,'liu','员工',300,'2019-03-19',3500,200.58,2);

3 员工扩展信息表 empext

字段名称

数据类型

是否为空

备注

empno

int

员工编号,PK主键

address

varchar(300)

Y

员工名称

phone

varchar(20)

Y

电话

cardno

varchar(20)

Y

省份证号

Mysql:

CREATE TABLE `empext` (

  `empno` int(11) NOT NULL,

  `address` varchar(300) DEFAULT NULL,

  `phone` varchar(20) DEFAULT NULL,

  `cardno` varchar(20) DEFAULT NULL,

  PRIMARY KEY (`empno`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

9基础函数

lower转小写

SELECT 'ABC',LOWER('ABC');

SELECT LOWER(dname),UPPER(dname) FROM dept;

upper转大写

SELECT LOWER(dname),UPPER(dname) FROM dept;

length长度

SELECT dname,LENGTH(dname) FROM dept;

substr切割字符串

SELECT dname,SUBSTR(dname,1,3) FROM dept;

concat拼接字符串

SELECT CONCAT(dname,'(',loc,')') FROM dept;

Aaa首字母大写

SELECT

dname,

SUBSTR(dname,1,1),UPPER(SUBSTR(dname,1,1)),

CONCAT(UPPER(SUBSTR(dname,1,1)),SUBSTR(dname,2,LENGTH(dname)))

FROM dept;

replace字符替换

SELECT loc,REPLACE(loc,'区','区域') FROM dept;

SELECT REPLACE(REPLACE(REPLACE(loc,'一',1),'二',2),'三',3) FROM dept;

round & ceil & floor

round四舍五入,ceil向上取整,floor向下取整

SELECT ename,

comm,ROUND(comm,1),ROUND(comm,2),

CEIL(comm),

FLOOR(comm) FROM emp;

uuid返回uuid

SELECT UUID()

SELECT

REPLACE(UUID(),'-','') UUID,

LENGTH(REPLACE(UUID(),'-','')) len

返回uuid:a08528ca-741c-11ea-a9a1-005056c00001

转义字符:\

单撇作为sql语句符号,内容中出现单撇就会乱套,进行转义即可

SELECT 'ab\'cde'

10日期函数

now获取当前时间

SELECT NOW(),CURDATE(),CURTIME(),SYSDATE()

select sysdate from dual #oracle当前时间,dual内置虚拟表

year & month & day

年月日,时分秒

SELECT hiredate,YEAR(hiredate) ,MONTH(hiredate),DAY(hiredate)

FROM emp

SELECT HOUR(NOW()),MINUTE(NOW()),SECOND(NOW()),NOW()

date_format

日期转字符串,注意格式的大小写,不错错误

SELECT DATE_FORMAT(NOW(),'%Y-%m-%d')

SELECT DATE_FORMAT(NOW(),'%Y-%m-%d %H:%i:%s')

last_day

每月最大日期

SELECT LAST_DAY(NOW())

SELECT ename,hiredate,LAST_DAY(hiredate) FROM emp

#每月的第一天和最后一天

SELECT DATE_FORMAT(hiredate,'%Y-%m-01'),LAST_DAY(hiredate) FROM emp

str_to_date

字符串转日期

SELECT STR_TO_DATE('2020-05-08','%Y-%m-%d')

11条件查询

distinct

去除重复的记录行

SELECT loc FROM dept;

SELECT DISTINCT loc FROM dept;

where

Oracle区分大小写,Mysql不区分大小写

SELECT * FROM emp WHERE 1=1;

SELECT * FROM emp WHERE 1=0;

SELECT * FROM emp WHERE empno=100;

SELECT * FROM emp WHERE ename='tony' AND deptno=2;

SELECT * FROM emp WHERE ename='tony' AND deptno=1;

#Oracle区分大小写,Mysql不区分大小写

SELECT * FROM dept WHERE dname='ACCOUNTING';

SELECT * FROM dept WHERE dname='Accounting';

SELECT * FROM dept WHERE dname='accounting';

case when..then..else end

类似java的if-elseif-else选择,根据条件展示值

SELECT nickname,user_name,

CASE WHEN user_rank = '5' THEN '经销商'

WHEN user_rank = '6' THEN '代理商'

WHEN user_rank = '7' THEN 'VIP'

ELSE '注册用户' END AS user_rank

end

FROM at_users

like

通配符%代表0到n个字符,通配符下划线_代表1个字符

SELECT * FROM emp WHERE ename LIKE 't%'; #t字母开头,效率高

SELECT * FROM emp WHERE ename LIKE '%n%'; #中间含有n,惯用

SELECT * FROM emp WHERE ename LIKE 't___'; #3个下划线

SELECT * FROM emp WHERE ename LIKE '__n%'; #2个下划线

and & or

and并且,or或者

SELECT * FROM dept WHERE dname='accounting' AND loc='一区';

SELECT * FROM dept WHERE dname='accounting' OR loc='二区';

null

SELECT * FROM emp WHERE mgr IS NULL; #字段内容为null的

SELECT * FROM emp WHERE mgr IS NOT NULL; #字段内容不为null的

nvl

字段值为null时替换,mgr为null替换为‘无’,comm数字替换为0

SELECT nvl(mgr,'空'),nvl(comm,0) FROM emp

between-and

between x and y 在x和y之间的值 [x,y]

SELECT * FROM emp

WHERE sal BETWEEN 5000 AND 10000;

等价于

SELECT * FROM emp

WHERE sal >= 5000 AND sal <= 10000;

union

把多个结果集合并,前提条件,两个结果集列对应,个数和类型一致

SELECT * FROM emp WHERE empno=100

UNION

SELECT * FROM emp WHERE empno=200

#报错:The used SELECT statements have a different number of columns

SELECT * FROM emp

UNION

SELECT * FROM dept

#字段个数相同,类型相同,下面SQL没有实际意义

SELECT empno,ename FROM emp

UNION

SELECT deptno,dname FROM dept

limit

limit n,返回前n条。

SELECT * FROM emp LIMIT 3    #返回前3条

SELECT * FROM emp LIMIT 0,3  #返回从0开始,取3条

SELECT * FROM emp LIMIT 1,3  #返回从1开始,取3条

Oredr By:排序

DESC:降序

ASC:升序

12聚合函数 aggregation

count记录总数

select * from emp;

select count(*) from emp;

select count(1) from emp;

select count(empno) from emp;

习惯使用*的方式,推荐使用后两种方式

max最大值

SELECT MAX(sal) FROM emp;

SELECT MAX(empno),MAX(sal),MAX(comm) FROM emp; 

min最小值

SELECT MIN(sal) FROM emp;

SELECT MIN(sal),MAX(sal) FROM emp;

avg平均值

SELECT AVG(sal) FROM emp

sum合计

SELECT SUM(sal) FROM emp

SELECT SUM(sal),SUM(comm) FROM emp;

13分组 group

group by

1)group by 用于对查询的结果进行分组统计

2)结果中的非聚合列必须出现在分组

SELECT deptno,MAX(sal),AVG(sal) FROM emp

GROUP BY deptno

ORDER BY MAX(sal)

#每个部门每个岗位的最高薪资和平均薪资,结果中的非聚合列必须出现在分组中,否则业务意义不对

SELECT deptno,job,MAX(sal),AVG(sal) FROM emp

GROUP BY deptno,job

ORDER BY MAX(sal)

having

having 子句类似where限制返回结果,where用在主句中,having用在分组中

分组后数据的过滤,having专门配合groupby

#平均工资小于8000的部门

SELECT deptno,AVG(sal) FROM emp

GROUP BY deptno

HAVING AVG(sal)<8000

#学生姓名重名名单*

SELECT NAME,COUNT(NAME) FROM student

GROUP BY NAME

HAVING COUNT(NAME)>1

14 注意事项

1 char和varchar区别

1)char为定长字符串,最大为255

2)varchar为不定长字符串,最大长度为65535

3)char会用空格补齐;而varchar只有固定长度

2 datetime和timestamp有什么区别?

1)date日期、time时间、datetime日期+时间、timestamp时间戳

2)datetime日期+时间,存储和显示是一样的

3)timestamp时间戳,存储的不是个日期,而是从1970年1月1日到指定日期的毫秒数

3中文乱码

如果在dos命令下执行insert插入中文数据,数据乱码,那现在sqlYog客户端执行下面命令:

set names utf8;

set names gbk;

1)设置客户端字符集和服务器端相同。两个都尝试下,哪个最后操作完成,查询数据库不乱码,就用哪个。

2)Mysql数据库默认字符集是lantin1,也就是以后网页中遇到的ISO8859-1,它是英文字符集,不支持存放中文。我们创建库时,可以指定字符集:

create database yhdb charset utf8;

3)保证创建数据库时用utf8,使用可视化工具一般就基本正确。

4别名

select * from tb_user; #查询所有记录

select name from tb_user; #查询tb_user表的name字段

select name as n1 from tb_user; #查询tb_user的name字段,结果显示为n1

5注释

/* 很多注释内容 */

# 一行注释内容

-- 一行注释内容,这个使用较多

6主键、外键、唯一索引的区别?

Primary Key   主键约束,自动创建唯一索引

Foreign Key   外键约束,外键字段的内容是引用另一表的字段内容

Unique Index  唯一索引,唯一值但不是主键,

数据库会进行检查,违反约束会报错,操作失败

7drop、delete和truncate之间的区别

1)drop删除库或者表,数据和表结构

2)delete和truncate只是删除表的数据

3)delete可以指定where条件,删除满足条件的记录,tuncate删除所有记录

4)对于自增字段的表,delete不会自增值清零,而truncate是把表记录和定义都删除了,然后重建表的定义,所以自增主键会重头开始计数

15 事务 transaction

1 事务4个条件

一般来说,事务是必须满足4个条件

1)原子性:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。

事务在执行过程中如果发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

2)一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。

3)隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力。

隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。

事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

4)持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

2使用前提

1)在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务

2)事务处理可以用来维护数据的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行

3)事务用来管理 insert、update、delete 语句,因为这些操作才会“破坏”数据,查询select语句是不会的

4)默认MySQL数据库的事务是开启,执行SQL后自动提交

3提交 commit

#多条语句时,批量执行,事务提交

SET @@autocommit = 0;

BEGIN;

INSERT INTO student (id) VALUES(5);

UPDATE student SET NAME='陈曦' WHERE id=5;

COMMIT;

#有了事务,多步操作就形成了原子性操作,高并发下也不会引起数据错乱

4回滚 rollback

#多条语句,批量执行,insert插入重复的主键导致失败,事务回滚

SET @@autocommit = 0;

BEGIN;

INSERT INTO student (id) VALUES(5);

UPDATE student SET NAME='陈曦2' WHERE id=5;

ROLLBACK;

5保存点 savepoint

删除数据是非常危险,怎么防止误操作?

先设置存储点,如果发现发现误操作删了数据,还可以回滚

#先设置手动提交,默认是自动提交

SET @@autocommit = 0;

SAVEPOINT chen;

DELETE FROM student;

ROLLBACK TO chen;

RELEASE SAVEPOINT chen;

COMMIT; #提交之后检查点就自动作废,删除了

16子查询 subquery

1概念

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

子查询执行效率低。记录少时效率影响不大、图方便直接使用,记录多时最好使用其它方式替代。

1单行子查询

返回结果为一个

--列出tony所在部门的所有人员

select deptno from emp where ename='tony';

select * from emp where deptno = (select deptno from emp where ename='tony');

deptno = 使用等号,后面的查询结果只能为一个值

2多行子查询

in子查询

select * from emp where job in ('经理','员工');

select * from emp where job in (select distinct job from emp);

17 多表联查 join

1 多表联查

多表查询是指基于两个和两个以上的表的查询。在实际应用中,查询单个表可能不能满足你的需求,如显示员工表emp中不只显示deptno,还要显示部门名称,而部门名称dname在dept表中。

#把两个表的数据都拼接起来

SELECT * FROM dept,emp

#查询出员工编号、员工工资及所在部门的名称

SELECT

 d.dname,

 e.empno,e.ename,e.sal

 FROM emp e,dept d

1)多表查询都是先生成笛卡尔积,再进行数据的筛选过滤。

2)多表查询过程中,现在内存中构建一个大大的结果集,然后进行数据的过滤

3)构建过程,使用的内存资源,包括过滤时的判断,都是既耗费资源,又浪费时间。因此,阿里规范中禁止3张表以上的联查

2 内连接 inner join

列出两张表都有的数据。

#显示部门2的员工和工资

SELECT * FROM emp e, dept d #会列出两张表的所有字段

WHERE e.deptno=d.deptno AND e.deptno=2

SELECT d.dname,e.ename,e.sal FROM emp e,dept d

WHERE e.deptno=d.deptno AND e.deptno=2

SELECT

 d.dname,e.ename,e.job

FROM

  (SELECT deptno,dname FROM dept) d

INNER JOIN

  (SELECT deptno,ename,job FROM emp) e

ON d.deptno = e.deptno

WHERE d.deptno=2

3左连接 left join

关联到的数据,从右表加入左表

SELECT

  d.dname,e.ename,e.job

FROM

(SELECT deptno,dname FROM dept) d

LEFT JOIN

(SELECT deptno,ename,job FROM emp) e

ON d.deptno=e.deptno

4右连接 right join

关联到的数据从左表加入右表,可以转化为左连接

select

  d.dname,e.ename,e.job

from

(select deptno,dname from dept) d

right join

(select deptno,ename,job from emp) e

on d.deptno = e.deptno

5万能连接

所有的连接方式都可以转换为左连接!

左连接实现步骤

第一步:左边查询括号写别名

第二步:右边查询括号写别名

第三步:left join横中间后面加on是条件

第四步:select挑字段别名后面写字段

18索引 index

1定义

1)索引是一种排好序的快速查找的数据结构,帮助数据库高效检索数据。

2)一般来说索引本身也很大,不可能全部存储在内存中,因此往往以索引文件的形式存放在磁盘中。

3)目前大多数索引都采用BTree树方式构建。

2分类

单值索引:一个索引只包括一个列,一个表可以有多个列

唯一索引:索引列的值必须唯一,但允许有空值

复合索引:一个索引同时包括多列

3优缺点

优点:

1)索引是数据库优化

2)表的主键会默认自动创建唯一索引

3)降低磁盘读写成本,极大提高检索速度

4)索引事先对数据进行排序提高查询的速度降低CPU的消耗

缺点:

1)索引本身也是一张表,保存主键与索引字段,并指向实体表的记录,所以索引列也要占用空间

2)索引表中的内容,在业务表中都有,数据是重复的,空间是“浪费的”

3)虽然索引大大提高查询的速度,但反向影响增、删、改操作的效率

4)随着业务不断变化,之前建立的索引可能不能满足查询需求,需要更新索引

4创建索引

ALTER TABLE empext ADD UNIQUE (phone)

ALTER TABLE empext ADD UNIQUE (cardno)

ALTER TABLE empext ADD INDEX phone_cardno_idx (phone,cardno)

SHOW INDEX FROM empext

5检查索引

EXPLAIN SELECT * FROM tb_user

EXPLAIN SELECT * FROM tb_user WHERE id=1

ALTER TABLE tb_user ADD UNIQUE (phone)

EXPLAIN SELECT * FROM tb_user WHERE phone='13572801415'

6判断是否创建索引

创建索引:

1)频繁出现在where查询条件的字段

2)多表查询中与其它表进行on关联的字段,外键关系

3)查询中经常用来排序的字段

4)查询中经常用来统计或者分组字段

5)单列索引/复合索引的选择? 高并发下倾向于创建复合索引

不创建索引:

1)频繁更新的字段: 每次更新都会影响索引树

2)where条件查询中用不到的字段

3)表记录太少

4)经常增删改的表: 更新了表,索引也得更新才行

5)如果一张表中重复的记录非常多,建立索引没有太大意义

7索引为什么快?

1)对数据排序

2)使用树形结构,类似二分查找,效率快

19 MySql执行顺序

1)FROM [left_table]:选择表

2)ON <join_condition>:链接条件

3)<join_type> JOIN <right_table>:链接

4)WHERE:条件过滤

5)GROUP BY:分组

6)AGG_FUNC:聚合

7)HAVING:分组过滤

8)SELECT:选择

9)DISTINCT:选择字段、去重

10)ORDER BY :排序

11)LIMIT count OFFSET count:分页

20 基础SQL优化

1 查询SQL尽量不要使用select *,而是具体字段

1)只取需要的字段,节省资源、减少网络开销

2)select * 进行查询时,很可能不会用到索引,就会造成全表扫描

反例:

SELECT * FROM student

正例:

SELECT id,NAME FROM student

2去重distinct过滤字段要少

#索引失效

EXPLAIN

SELECT DISTINCT * FROM student

#索引生效

EXPLAIN

SELECT DISTINCT id,NAME FROM student

EXPLAIN

SELECT DISTINCT NAME FROM student

3 使用varchar代替char

1)varchar变长字段按数据内容实际长度存储,存储空间小,可以节省存储空间

2)char按声明大小存储,不足补空格

3)对于查询来说,在一个较小的字段内搜索,效率更高

反例:

`deptname`char(100) DEFAULT NULL COMMENT '部门名称'

正例:

`deptname` varchar(100) DEFAULT NULL COMMENT '部门名称'

4 尽量使用数值替代字符串类型

1)主键(id):primary key优先使用数值类型int,tinyint

2)性别(sex):0-代表女,1-代表男

3)支付方式(payment):1-现金、2-微信、3-支付宝、4-信用卡、5-银行卡

4)服务状态(state):1-开启、2-暂停、3-停止

5)商品状态(state):1-上架、2-下架、3-删除

5 查询尽量避免返回大量数据

1)如果查询数据量很大,查询时间过长,网络传输时间过长

2)返回很多数据,用户看不过来

3)通常采用分页

6使用explain分析SQL是否使用了索引

EXPLAIN

SELECT * FROM student WHERE id=1

返回结果:

是否使用索引及其扫描类型

type:

1)ALL 全表扫描没有优化最慢的方式

2)index 索引全扫描

3)range 索引范围扫描,常用语<,<=,>=,between等操作

4)ref 使用非唯一索引或唯一索引前缀,返回单条记录,常出现在关联查询中

5)eq_ref 类似ref,区别在于使用的是唯一索引,使用主键的关联查询

6)const/system 单条记录,系统会把匹配行中的其他列作为常数处理,如主键或唯一索引查询

7)null MySQL不访问任何表或索引,直接返回结果

8)possible_keys:显示可能应用在这张表中的索引

9)key:真正使用的索引方式

7 优化like语句先写一个字符在使用%号,才会走索引

like可能让索引失效

反例:

EXPLAIN

SELECT id,NAME FROM student WHERE NAME LIKE '%1'

EXPLAIN

SELECT id,NAME FROM student WHERE NAME LIKE '%1%'

正例:

EXPLAIN

SELECT id,NAME FROM student WHERE NAME LIKE '1%'

8 索引不宜太多,一般5个以内

1)索引并不是越多越好,虽其提高查询的效率,但却会降低插入和更新的效率

2)索引可以存储数据,占空间

3)索引表的数据要排序,排序要花时间

4)insert或update时有可能会重建索引,如果数据量巨大,重建将进行记录的重新排序

5)一个表的索引数最好不要超过5个

9索引不适合建在有大量重复数据的字段上

如性别字段。如果索引列有大量重复数据,Mysql查询优化器推算发现不走索引的成本更低,很可能就放弃索引。

10 避免在内置函数中使用索引列

可能会导致索引失效

反例:

EXPLAIN

SELECT * FROM student

WHERE DATE_ADD(birthday,INTERVAL 7 DAY) >=NOW();

正例:

EXPLAIN

SELECT * FROM student

WHERE  birthday >= DATE_ADD(NOW(),INTERVAL 7 DAY);

11 where限定查询的数据

需要什么数据,就去查什么数据,避免返回不必要的数据,节省开销

反例:

SELECT id,NAME FROM student WHERE sex='男'

正例:

SELECT id,NAME FROM student WHERE id=1 AND sex='男'

12避免在where中对字段进行表达式操作

如果字段相关的是表达式就进行全表扫描

反例:

EXPLAIN

SELECT * FROM student WHERE id+1-1=+1

正例:

EXPLAIN

SELECT * FROM student WHERE id=+1-1+1

EXPLAIN

SELECT * FROM student WHERE id=1

13避免在where子句中使用!=或<>操作符

有操作符,会放弃使用索引而进行全表扫描。

反例:

EXPLAIN

SELECT * FROM student WHERE salary!=3000

14 where中使用默认值代替null

1)is null,is not null可能让索引失效

2)把null值,换成默认值,让走索引成为可能

反例:

EXPLAIN

SELECT * FROM student WHERE age IS NOT NULL

正例:

EXPLAIN

SELECT * FROM student WHERE age>0

15 避免在where子句中使用or来连接条件

1)使用or可能会使索引失效,从而全表扫描

反例:

SELECT * FROM student WHERE id=1 OR salary=30000

正例:

# 使用union all

SELECT * FROM student WHERE id=1

UNION ALL

SELECT * FROM student WHERE salary=30000

# 分开两条sql写

SELECT * FROM student WHERE id=1

SELECT * FROM student WHERE salary=30000

21 高级SQL优化

1 批量插入性能提升

1)大量数据提交,批量性能非常快,mysql独有

2)默认新增SQL有事务控制,导致每条都需要事务开启和事务提交;而批量处理是一次事务开启和提交,速度快。

多条提交:

INSERT INTO student (id,NAME) VALUES(4,'齐雷');

INSERT INTO student (id,NAME) VALUES(5,'刘昱江');

批量提交:

INSERT INTO student (id,NAME) VALUES(4,'齐雷'),(5,'刘昱江');

2避免批量删除修改过多数据,采取分批操作

1)避免同时修改或删除过多数据,因为会造成cpu利用率过高,会造成锁表,影响别人对数据库的访问。

2)采取分批操作如每次500

反例:

#一次删除10万或者100万+?

delete from student where id <100000;

#采用单一循环操作,效率低,时间漫长

for(User user:list){

  delete from student;}

正例:

//分批进行删除,如每次500

for(){

delete student where id<500;}

delete student where id>=500 and id<1000;

3伪删除设计

1)删除只是一个标识,并没有从数据库表中真正删除,可以作为历史记录备查

2)大型系统中,表关系是非常复杂的,不能直接删除,其它模块可能引用

3)伪删除的数据用户就看不到,不影响用户的使用

4)操作速度快,特别数据量很大情况下

商品状态:1-上架、2-下架、3-删除

4 先过滤,后分组高group by的效率

可以在执行到该语句前,把不需要的记录过滤掉

反例:先分组,再过滤

select job,avg(salary)from employee

group by job

having job ='president' or job ='managent';

正例:先过滤,后分组

select job,avg(salary) from employee

where job ='president' or job = 'managent' 

group by job;

5 复合索引最左特性

1)当创建复合索引的时,如(k1,k2,k3),相当于创建了(k1)、(k1,k2)和(k1,k2,k3)三个索引,这就是最左匹配原则

2)没有出现左边的字段复合索引不满足最左原则,索引会失效,跟Mysql优化器有关

3)满足复合索引的左侧顺序,哪怕只是部分,复合索引生效

创建复合索引,也就是多个字段

ALTER TABLE student ADD INDEX idx_name_salary (NAME,salary)

满足复合索引的左侧顺序,哪怕只是部分,复合索引生效

EXPLAIN

SELECT * FROM student WHERE NAME='陈子枢'

没有出现左边的字段,则不满足最左特性,索引失效

EXPLAIN

SELECT * FROM student WHERE salary=3000

复合索引全使用,按左侧顺序出现 name,salary,索引生效

EXPLAIN

SELECT * FROM student WHERE NAME='陈子枢' AND salary=3000

虽然违背了最左特性,但MYSQL执行SQL时会进行优化,底层进行颠倒优化

EXPLAIN

SELECT * FROM student WHERE salary=3000 AND NAME='陈子枢'

6 排序字段创建索引提高效率

7 删除冗余和重复的索引

8 不要有超过5个以上的表连接

1)关联的表个数越多,编译的时间和开销也就越大

2)每次关联内存中都生成一个临时表

3)阿里规范中,建议多表联查三张表以下

9 连接中,优先使用inner join如果使用left join左边表尽量小

10尽量使用union all替代union

1)union和union all的区别是,union会自动去重,而union all则将所有的结果全部显示出来

2)union:对两个结果集进行并集操作,并去重,同时进行默认规则排序

3)多数情况,重复数据不多。

反例:

SELECT * FROM student

UNION

SELECT * FROM student

正例:

SELECT * FROM student

UNION ALL

SELECT * FROM student

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/364657.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基础算法一:同向双指针

同向双指针——滑动窗口 讲解实例&#xff1a;LeetCode209. 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl1, …, numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合…

二叉树、二叉搜索树、二叉树的最近祖先、二叉树的层序遍历【零神基础精讲】

来源0x3f&#xff1a;https://space.bilibili.com/206214 文章目录二叉树[104. 二叉树的最大深度](https://leetcode.cn/problems/maximum-depth-of-binary-tree/)[111. 二叉树的最小深度](https://leetcode.cn/problems/minimum-depth-of-binary-tree/)[129. 求根节点到叶节点…

工时表软件在项目中的作用 帮助企业管理项目成员的工时

企业的不断发展离不开每一个成功交付的项目&#xff0c;但在任何一个项目中&#xff0c;人力成本是主要的成本之一&#xff0c;员工的工作效率高低影响着项目成本和质量的关键点。如果想要降低整个项目的成本那就需要对员工工时更加精准的把控&#xff0c;所以规范管理员工时间…

文 件 操 作

程序运行时产生的数据都属于临时数据&#xff0c;程序一旦运行结束都会被释放通过文件可以将数据持久化C中对文件操作需要包含头文件< fstream >文件类型分为两种:1.文本文件&#xff1a; 文件以文本的AScII码形式存储在计算机中2.二进制文件&#xff1a; 文件以文本的二…

java反序列化基础

序列化与反序列化 1、概述 序列化是让Java对象脱离Java运行环境的一种手段&#xff0c;可以有效的实现多平台之间的通信、对象持久化存储。 Java 序列化是指把 Java 对象转换为字节序列的过程便于保存在内存、文件、数据库中&#xff0c;ObjectOutputStream类的writeObject(…

计算几何原理与例题

目录 一、前言 二、简单几何 1、平面切分&#xff08;2020年省赛&#xff0c;lanqiaoOJ题号503&#xff09; 2、三角形的面积&#xff08;lanqiaoOJ题号1231&#xff09; 3、点和直线关系&#xff08;lanqiao0J题号1240&#xff09; 4、点和线段关系&#xff08;lanqiaoO…

活动回顾丨研发效能度量线下沙龙圆满举办

2月18日&#xff0c;由跬智信息&#xff08;Kyligence&#xff09;联合甄知科技主办的研发效能度量线下沙龙圆满举办。本次沙龙在 Kyligence 上海总部举办&#xff0c;Kyligence 联合创始人兼 CTO 李扬、腾讯 Tech Lead 茹炳晟&#xff0c;以及甄知科技创始人兼 CTO 张礼军在现…

ClickHouse学习笔记(一):ClickHouse架构概述(为什么ClickHouse这么快呢?)

文章目录1、ClickHouse 概述1.1 、简述1.2 、名词解释1.2.1 、MPP 架构1.2.2 、向量化执行引擎1.2.3 、SIMD1.2.4 、OLAP1.3、应用场景2、ClickHouse 核心特性2.1、完备的 DBMS 功能2.2、列式存储与数据压缩2.3、向量化执行引擎2.4、关系模型与SQL查询2.5、多样化的表引擎2.6、…

简单的C++:【运算符重载】新手易学

学过C语言的同志们应该都知道位运算符>> 和 << &#xff08;右移左移&#xff09;&#xff0c;但是这两个运算符在C中还是我们的输入和输出流操作符&#xff0c;那么这是为什么呢&#xff1f;&#xff0c;了解完本篇文章之后&#xff0c;我们再来回答这个问题。 C为…

python和C++代码实现模拟动态指针时钟

一、python代码实现及turtle库简单介绍 桌面时钟项目描述 1、使用turtle库绘制时钟外形及表针&#xff1b; 2、使用datetime获取系统时间&#xff1b; 3、时钟动态显示 turtle库基本命令 1、turtle.setup()函数&#xff1a;用于启动一个图形窗口&#xff0c;它有四个参数…

2023-02-22干活小计

复现BERT&#xff1a; 只能说爷今天干了一上午一下午的代码 bert的输入&#xff1a; batch_size * max_len * emb_num 768 * 768 bert的输出&#xff1a;三维字符级别特征(NER可能就更适合) 二维篇章级别特征(比如文本分类可能就更适合) batch_size * max_len * emb_num, ba…

亲身试验 Outlook防关联方法分享

Outlook在海外的用途是很广泛的&#xff0c;不仅可以用于收发邮件&#xff0c;还可以作为各类第三方网站的登录凭证。所以Microsoft对于Outlook的监管还是比较严格的&#xff0c;跨境卖家大量注册Outlook账号使用的话很容易被检测出关联然后被封号。龙哥针对Outlook防关联的问题…

35-Golang中的方法

Golang中的方法方法的介绍和使用方法的声明和调用方法的调用和传参机制原理方法的声明(定义)方法注意事项和细节讨论方法和函数的区别方法的介绍和使用 在某些情况下&#xff0c;我们需要声明(定义)方法。比如person结构体&#xff0c;除了有一些字段外(年龄&#xff0c;姓名……

unix高级编程-僵尸进程和孤儿进程

僵尸进程&#xff1a; 一个父进程利用fork创建子进程&#xff0c;如果子进程退出&#xff0c;而父进程没有利用wait 或者 waitpid 来获取子进程的状态信息&#xff0c;那么子进程的状态描述符依然保存在系统中。 孤儿进程&#xff1a;一个父进程退出&#xff0c; 而它的一个或…

java+Selenium+TestNg搭建自动化测试架构(3)实现POM(page+Object+modal)

1.Page Object是Selenium自动化测试项目开发实践的最佳设计模式之一&#xff0c;通过对界面元素的封装减少冗余代码&#xff0c;同时在后期维护中&#xff0c;若元素定位发生变化&#xff0c;只需要调整页面元素封装的代码&#xff0c;提高测试用例的可维护性。 PageObject设计…

软件测试,刚进入一个公司如何快速上手一个项目?

目录 前言 客观现状 主观能动性 总结感谢每一个认真阅读我文章的人&#xff01;&#xff01;&#xff01; 重点&#xff1a;配套学习资料和视频教学 前言 刚入职一家新公司&#xff0c;做的项目是之前很少接触的行业&#xff0c;该怎么快速的熟悉并上手自己的工作&#xf…

富文本编辑组件封装,tinymce、tinymce-vue

依赖&#xff1a;package.json yarn add tinymce tinymce/tinymce-vue {"dependencies": {"tinymce/tinymce-vue": "5.0.0","tinymce": "6.3.1","vue": "3.2.45",}, } 本地依赖&#xff1a; 在publ…

JIT-即时编译技术

VM&#xff08;HotSpot&#xff09;执行引擎中包含解释器与JIT编译器热点代码&#xff08;执行多次&#xff09;才有JIT编译的必要&#xff08;JIT编译阈值&#xff09;JVM&#xff08;HotSpot&#xff09;会有两个计数器&#xff08;次数/回边&#xff09;判断方法/代码块是否…

缺少IT人员的服装行业该如何进行数字化转型?

服装行业上、下游产业链长&#xff0c;产品属性复杂&#xff0c;是劳动密集型和技术密集型紧密结合的产物&#xff0c;是典型的实体经济代表。 近二十年是服装业发展的机遇和挑战之年&#xff0c;从“世界工厂”“中国制造”&#xff0c;逐渐向“中国设计”转变,中国服装产业经…

Kotlin新手教程九(协程)

一、协程 协程从Kotlin1.3开始引入&#xff0c;本质上协程就是轻量级的线程。协程的基本功能点有&#xff1a; 轻量&#xff1a;可以在单个线程上运行多个协程&#xff0c;因为协程支持挂起&#xff0c;不会使正在运行协程的线程阻塞。挂起比阻塞节省内存&#xff0c;且支持多…