MySql基础+特性+查询语句详解

137 阅读10分钟

本文已参与“新人创作礼”活动,一起开始掘金创作之路。

本文转载于 []((236条消息) MySql基础+特性+查询语句详解_.南风.的博客-CSDN博客)

简介

优点

1实现数据持久化

2结构化查询

概念

DB

DB:数据库(database):存储数据的“仓库”。它保存了一系列有组织的数据。

DBMS

DBMS:数据库管理系统(Database Management System)。数据库是通过DBMS创 建和操作的容器

SQL

SQL:结构化查询语言(Structure Query Language):专门用来与数据库通信的语 言

DML

DML(Data Manipulation Language):数据操纵语句,用于添 加、删除、修改、查询数据库记录,并检查数据完整性

INSERT:添加数据到数据库中
UPDATE:修改数据库中的数据
DELETE:删除数据库中的数据
SELECT:选择(查询)数数据

DDL

DDL(Data Definition Language):数据定义语句,用于库和 表的创建、修改、删除。

CREATE TABLE:创建数据库表
ALTER TABLE:更改表结构、添加、删除、修改列长度
DROP TABLE:删除表
CREATE INDEX:在表上建立索引
DROP INDEX:删除索引

DCL

DCL(Data Control Language):数据控制语句,用于定义用 户的访问权限和安全级别。

GRANT:授予访问权限
REVOKE:撤销访问权限
COMMIT:提交事务处理
ROLLBACK:事务处理回退
SAVEPOINT:设置保存点
LOCK:对数据库的特定部分进行锁

操作

1. 进入 mysql, 在命令行中输入: mysql –uroot –p#### (其中:####表示密码)
2. 查看 mysql 中有哪些个数据库: show databases; 
3. 使用一个数据库: use 数据库名称; 
4. 新建一个数据库: create database 数据库名 
5. 查看指定的数据库中有哪些数据表: show tables; 
6. 建表: create table
7. 查看表的结构:desc 表名 
8. 删除表: drop table 表名 
9. 查看表中的所有记录: select * from 表名;
10. 向表中插入记录:insert into 表名(列名列表) values(列对应的值的列表);
11. 注意:插入 varchar 或 date 型的数据要用 单引号 引起来
12. 修改记录: update 表名 set 列1 = 列1的值, 列2 = 列2的值 where …
13. 删除记录: delete from 表名 where …

基础查询

查询全部

 SELECT *  
 FROM departments;

查询指定列

 SELECT department_id, location_id  
 FROM departments;

起别名

  SELECT last_name AS name, commission_pct comm 
  FROM employees;

显示表结构

 DESCRIBE employees

WHERE

 SELECT employee_id, last_name, job_id, department_id 
 FROM employees
 WHERE department_id = 90

比较

 SELECT last_name, salary 
 FROM employees 
 WHERE salary <= 3000

BETWEEN

SELECT last_name, salary 
FROM employees 
WHERE salary BETWEEN 2500 AND 3500;

IN

 SELECT employee_id, last_name, salary, manager_id 
 FROM employees WHERE
 manager_id IN (100, 101, 201);

LIKE – % 代表零个或多个字符(任意个字符)。 注意:不能表示NULL – _ 代表一个字符。

SELECT first_name  
FROM employees  
WHERE first_name 
LIKE 'S%'

NULL

SELECT first_name  
FROM employees  
WHERE first_name 
LIKE 'S%'

AND

SELECT employee_id, last_name, job_id, salary  
FROM employees  
WHERE salary >=10000  
AND job_id LIKE '%MAN%'

OR

SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary >= 10000
OR job_id LIKE '%MAN%'

NOT

SELECT last_name, job_id
FROM employees
WHERE job_id 
NOT IN ('IT_PROG', 'ST_CLERK', 'SA_REP')

去重

SELECT DISTINCT job_id
FROM employees
WHERE job_id 
NOT IN ('IT_PROG', 'ST_CLERK', 'SA_REP')

+

作用:做加法运算
select 数值+数值; 直接运算
select 字符+数值;先试图将字符转换成数值,如果转换成功,则继续运算;否则转换成0,再做运算
select null+值;结果都为null

Concat

功能:拼接字符
select concat(last_name,'_',first_name);

IF NULL

功能:判断某字段或表达式是否为null,如果为null 返回指定的值,否则返回原本的值
select ifnull(commission_pct,0) from employees;

排序查询

ODER BY – ASC(ascend): 升序 – DESC(descend): 降序

SELECT last_name, job_id, department_id, hire_date
FROM employees
ORDER BY hire_date 
SELECT employee_id, last_name, salary*12 AS annsal
FROM employees
ORDER BY annsal;
SELECT last_name, department_id, salary
FROM employees
ORDER BY department_id, salary DESC/ASC;

函数-单行函数

字符函数

LOWER('SQL Course')		 	 sql course
UPPER('SQL Course')			 SQL COURSE
CONCAT('Hello', 'World')     HelloWorld
SUBSTR('HelloWorld',1,5)     Hello
LENGTH('HelloWorld')         10
INSTR('HelloWorld', 'W')	 6
LPAD(salary,10,'*')          *****24000
RPAD(salary, 10, '*')        24000*****
TRIM('H' FROM 'HelloWorld')  elloWorld
REPLACE('abcd','b','m')      amcd

数学函数

ROUND: 四舍五入
 	ROUND(45.926, 2) 45.93
TRUNCATE: 截断
	TRUNC(45.926, 2) 45.92
MOD: 求余
 	MOD(1600, 300) 100

日期函数

• now:获取当前日期
• str_to_date: 将日期格式的字符转换成指定格式的日期
STR_TO_DATE('9-13-1999','%m-%d-%Y') 1999-09-13date_format:将日期转换成字符
DATE_FORMAT(‘2018/6/6’,‘%Y年%m月%d日’) 20180606

流程控制函数

SELECT last_name, job_id, salary,
CASE job_id 
WHEN 'IT_PROG' THEN 1.10*salary
WHEN 'ST_CLERK' THEN 1.15*salary
WHEN 'SA_REP' THEN 1.20*salary
ELSE salary 
END "REVISED_SALARY"
FROM employees;

函数-分组函数

1、sum、avg一般用于处理数值型 max、min、count可以处理任何类型 2、以上分组函数都忽略null值

3、可以和distinct搭配实现去重的运算

AVG()

SELECT AVG(salary) FROM employees;

COUNT()

SELECT COUNT(salary) FROM employees;


SELECT COUNT(*) FROM employees;

SELECT COUNT(1) FROM employees;
count中没有的字段自动加一列

效率:
MYISAM存储引擎下  ,COUNT(*)的效率高
INNODB存储引擎下,COUNT(*)和COUNT(1)的效率差不多,比COUNT(字段)要高一些

MAX()

SELECT MAX(salary) FROM employees;

MIN()

SELECT MIN(salary) FROM employees;

SUM()

SELECT SUM(salary) FROM employees;

限制


和分组函数一同查询的字段有限制

SELECT AVG(salary),employee_id  FROM employees;
         一行          很多行    所以需加group by

分组查询

			使用关键字		筛选的表	             位置
分组前筛选	where			原始表	   	     group by的前面
分组后筛选	having		  分组后的结果	     group by 的后面

基础

查询每个工种的员工平均工资
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;

分组前筛选

查询邮箱中包含a字符的 每个部门的最高工资

SELECT MAX(salary),department_id
FROM employees
WHERE email LIKE '%a%'
GROUP BY department_id;

分组后筛选


#案例:查询哪个部门的员工个数>5

#①查询每个部门的员工个数
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id;

#② 筛选刚才①结果

SELECT COUNT(*),department_id
FROM employees

GROUP BY department_id

HAVING COUNT(*)>5;
领导编号>102的每个领导手下的最低工资大于5000的领导编号和最低工资

manager_id>102

SELECT manager_id,MIN(salary)
FROM employees
WHERE manager_id>102
GROUP BY manager_id
HAVING MIN(salary)>5000;

添加排序

#案例:每个工种有奖金的员工的最高工资>6000的工种编号和最高工资,按最高工资升序

SELECT job_id,MAX(salary) m
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING m>6000
ORDER BY m ;

按多个字段

按多个字段分组

#案例:查询每个工种每个部门的最低工资,并按最低工资降序

SELECT MIN(salary),job_id,department_id
FROM employees
GROUP BY department_id,job_id
ORDER BY MIN(salary) DESC;

连接查询

在这里插入图片描述 在这里插入图片描述

sql92内连接

等值连接

① 多表等值连接的结果为多表的交集部分 ②n表连接,至少需要n-1个连接条件 ③ 多表的顺序没有要求 ④一般需要为表起别名 ⑤可以搭配前面介绍的所有子句使用,比如排序、分组、筛选

查询女神名和对应的男神名
SELECT NAME,boyName 
FROM boys,beauty
WHERE beauty.boyfriend_id= boys.id;

起别名。 注意:如果为表起了别名,则查询的字段就不能使用原来的表名去限定


#查询员工名、工种号、工种名

SELECT e.last_name,e.job_id,j.job_title
FROM employees  e,jobs j
WHERE e.`job_id`=j.`job_id`;

加筛选

#案例:查询有奖金的员工名、部门名

SELECT last_name,department_name,commission_pct

FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`
AND e.`commission_pct` IS NOT NULL;

加分组

查询每个城市的部门个数

SELECT COUNT(*) 个数,city
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
GROUP BY city;

加排序



#案例:查询每个工种的工种名和员工的个数,并且按员工个数降序

SELECT job_title,COUNT(*)
FROM employees e,jobs j
WHERE e.`job_id`=j.`job_id`
GROUP BY job_title
ORDER BY COUNT(*) DESC;

三表连接

#案例:查询员工名、部门名和所在的城市

SELECT last_name,department_name,city
FROM employees e,departments d,locations l
WHERE e.`department_id`=d.`department_id`
AND d.`location_id`=l.`location_id`
AND city LIKE 's%'

ORDER BY department_name DESC;

非等值连接

查询员工的工资和工资级别


SELECT salary,grade_level
FROM employees e,job_grades g
WHERE salary BETWEEN g.`lowest_sal` AND g.`highest_sal`
AND g.`grade_level`='A';

自连接

#案例:查询 员工名和上级的名称

SELECT e.employee_id,e.last_name,m.employee_id,m.last_name
FROM employees e,employees m
WHERE e.`manager_id`=m.`employee_id`;


sql99内连接

等值连接

查询名字中包含e的员工名和工种名(添加筛选)
SELECT last_name,job_title
FROM employees e
INNER JOIN jobs j
ON e.`job_id`=  j.`job_id`
WHERE e.`last_name` LIKE '%e%';
查询部门个数>3的城市名和部门个数,(添加分组+筛选)

#①查询每个城市的部门个数
#②在①结果上筛选满足条件的
SELECT city,COUNT(*) 部门个数
FROM departments d
INNER JOIN locations l
ON d.`location_id`=l.`location_id`
GROUP BY city
HAVING COUNT(*)>3;

非等值连接


 #查询工资级别的个数>20的个数,并且按工资级别降序
 SELECT COUNT(*),grade_level
FROM employees e
 JOIN job_grades g
 ON e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`
 GROUP BY grade_level
 HAVING COUNT(*)>20
 ORDER BY grade_level DESC;
 

自连接

  #查询姓名中包含字符k的员工的名字、上级的名字
 SELECT e.last_name,m.last_name
 FROM employees e
 JOIN employees m
 ON e.`manager_id`= m.`employee_id`
 WHERE e.`last_name` LIKE '%k%';

外连接

用于查询一个表中有,另一个表没有的记录

外连接的查询结果为主表中的所有记录
	如果从表中有和它匹配的,则显示匹配的值
	如果从表中没有和它匹配的,则显示null
	外连接查询结果=内连接结果+主表中有而从表没有的记录

左外连接


 #案例1:查询哪个部门没有员工
 #左外
 SELECT d.*,e.employee_id
 FROM departments d
 LEFT OUTER JOIN employees e
 ON d.`department_id` = e.`department_id`
 WHERE e.`employee_id` IS NULL;

右外连接

 #右外
 
  SELECT d.*,e.employee_id
 FROM employees e
 RIGHT OUTER JOIN departments d
 ON d.`department_id` = e.`department_id`
 WHERE e.`employee_id` IS NULL;
 

全外连接

 #全外
 
 
 USE girls;
 SELECT b.*,bo.*
 FROM beauty b
 FULL OUTER JOIN boys bo
 ON b.`boyfriend_id` = bo.id;
 

交叉连接

 #交叉连接
 类似于笛卡尔积
 SELECT b.*,bo.*
 FROM beauty b
 CROSS JOIN boys bo;
 

子查询

概念:出现在其他语句内部的select语句,称为子 查询或内查询 内部嵌套其他select语句的查询,称为外查询或主 查询

位于having后面

标量子查询

    #1.	查询和Zlotkey相同部门的员工姓名和工资

#①查询Zlotkey的部门
SELECT department_id
FROM employees
WHERE last_name = 'Zlotkey'

#②查询部门号=①的姓名和工资
SELECT last_name,salary
FROM employees
WHERE department_id = (
	SELECT department_id
	FROM employees
	WHERE last_name = 'Zlotkey'

)

多行子查询

#案例1:返回location_id是14001700的部门中的所有员工姓名

#①查询location_id是14001700的部门编号
SELECT DISTINCT department_id
FROM departments
WHERE location_id IN(1400,1700)

#②查询员工姓名,要求部门号是①列表中的某一个

SELECT last_name
FROM employees
WHERE department_id  <>ALL(
	SELECT DISTINCT department_id
	FROM departments
	WHERE location_id IN(1400,1700)


);

多列子查询

#案例:查询员工编号最小并且工资最高的员工信息



SELECT * 
FROM employees
WHERE (employee_id,salary)=(
	SELECT MIN(employee_id),MAX(salary)
	FROM employees
);

#①查询最小的员工编号
SELECT MIN(employee_id)
FROM employees


#②查询最高工资
SELECT MAX(salary)
FROM employees


#③查询员工信息
SELECT *
FROM employees
WHERE employee_id=(
	SELECT MIN(employee_id)
	FROM employees


)AND salary=(
	SELECT MAX(salary)
	FROM employees

);

位于select后面

只有标量子查询


#案例:查询每个部门的员工个数


SELECT d.*,(

	SELECT COUNT(*)
	FROM employees e
	WHERE e.department_id = d.`department_id`
 ) 个数
 FROM departments d;

位于from后面

将子查询结果充当一张表,要求必须起别名

#案例:查询每个部门的平均工资的工资等级
#①查询每个部门的平均工资
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id


SELECT * FROM job_grades;


#②连接①的结果集和job_grades表,筛选条件平均工资 between lowest_sal and highest_sal

SELECT  ag_dep.*,g.`grade_level`
FROM (
	SELECT AVG(salary) ag,department_id
	FROM employees
	GROUP BY department_id
) ag_dep
INNER JOIN job_grades g
ON ag_dep.ag BETWEEN lowest_sal AND highest_sal;

位于exists后面


#案例2:查询没有女朋友的男神信息

#in

SELECT bo.*
FROM boys bo
WHERE bo.id NOT IN(
	SELECT boyfriend_id
	FROM beauty
)

#exists
SELECT bo.*
FROM boys bo
WHERE NOT EXISTS(
	SELECT boyfriend_id
	FROM beauty b
	WHERE bo.`id`=b.`boyfriend_id`

);


分页查询


应用场景:当要显示的数据,一页显示不全,需要分页提交sql请求
语法:
	select 查询列表
	from 表
	【join type join 表2
	on 连接条件
	where 筛选条件
	group by 分组字段
	having 分组后的筛选
	order by 排序的字段】
	limit 【offset,】size;
	
	offset要显示条目的起始索引(起始索引从0开始)
	size 要显示的条目个数
特点:
	①limit语句放在查询语句的最后
	②公式
	要显示的页数 page,每页的条目数size
	
	select 查询列表
	from 表
	limit (page-1)*size,size;
	
	size=10
	page  
	1	0
	2  	10
	3	20
#案例1:查询前五条员工信息


SELECT * FROM  employees LIMIT 0,5;
SELECT * FROM  employees LIMIT 5;


#案例2:查询第11条——第25SELECT * FROM  employees LIMIT 10,15;

联合查询

用于将没有相关关系的两个表的查询结果进行合并。

特点:★
1、要求多条查询语句的查询列数是一致的!
2、要求多条查询语句的查询的每一列的类型和顺序最好一致
3、union关键字默认去重,如果使用union all 可以包含重复项

*/


#引入的案例:查询部门编号>90或邮箱包含a的员工信息

SELECT * FROM employees WHERE email LIKE '%a%' OR department_id>90;;

SELECT * FROM employees  WHERE email LIKE '%a%'
UNION
SELECT * FROM employees  WHERE department_id>90;

DML增删改数据

插入

/*
语法:
insert into 表名(列名,...) values(值1,...);

*/
SELECT * FROM beauty;
#1.插入的值的类型要与列的类型一致或兼容
INSERT INTO beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
VALUES(13,'唐艺昕','女','1990-4-23','1898888888',NULL,2);

#2.不可以为null的列必须插入值。可以为null的列如何插入值?
#方式一:
INSERT INTO beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
VALUES(13,'唐艺昕','女','1990-4-23','1898888888',NULL,2);

#方式二:

INSERT INTO beauty(id,NAME,sex,phone)
VALUES(15,'娜扎','女','1388888888');


#3.列的顺序是否可以调换
INSERT INTO beauty(NAME,sex,id,phone)
VALUES('蒋欣','女',16,'110');


#4.列数和值的个数必须一致

INSERT INTO beauty(NAME,sex,id,phone)
VALUES('关晓彤','女',17,'110');

#5.可以省略列名,默认所有列,而且列的顺序和表中列的顺序一致

INSERT INTO beauty
VALUES(18,'张飞','男',NULL,'119',NULL,NULL);

#6.支持多行

INSERT INTO beauty
VALUES(23,'唐艺昕1','女','1990-4-23','1898888888',NULL,2)
,(24,'唐艺昕2','女','1990-4-23','1898888888',NULL,2)
,(25,'唐艺昕3','女','1990-4-23','1898888888',NULL,2);

#7.支持子查询

INSERT INTO beauty(id,NAME,phone)
SELECT id,boyname,'1234567'
FROM boys WHERE id<3;

修改

#1.修改单表的记录
#案例1:修改beauty表中姓唐的女神的电话为13899888899

UPDATE beauty SET phone = '13899888899'
WHERE NAME LIKE '唐%';

#案例2:修改boys表中id好为2的名称为张飞,魅力值 10
UPDATE boys SET boyname='张飞',usercp=10
WHERE id=2;

删除

持续更新中。。。