Mysql从0到0.9-DML&DQL

152 阅读6分钟

Mysql从0到0.9

本章总结DML数据库操作语言,以及数DQL据库查询语言的基本使用

    上一篇Mysql基础    ←||→    下一篇常用函数&聚合函数

DML

Data Manipulation Language(数据库操作语言)

insert into tablename(字段名1.。。。) values('值1'。。。。)--一一对应
##批量插入
insert into tablename(字段名1.。。。) values('值1'。。。。),('值1'。。。。),--一一对应
UPDATE  tablename SET 字段名1 = '2021-01-02 11:12:19' WHERE id = 2
delete from tablename where id = 1 
##批量删除
delete from tablename
## 属于ddl  数据定义语言
truncate tablename 、truncate table tablename 

drop删除表数据及结构、delete,truncate删除数据保留表结构

delete 和 truncate区别
  • delete逐行删除,效率慢、可回滚。truncate立刻回退状态,立刻生效,效率快,不可回滚
  • 对于自增列来说delete不会将自增列回退到1(但是重启mysql服务会查询最大自增列max,回退到1.原因就是innodb对于自增列大部分是主键索引会存放在内存中,重启服务内存会清空)。truncate会回退到1
  • 对于有被外键约束的表不能使用truncate

小总:想要快速清空一张表,不要求回滚事务使用truncate,但是做好备份。想要删除部分数据,并且要求回滚且支持事务使用delete。


常用操作符和关键字

基本比较操作符: = 、>、 <、 >=、 <= 、!=、 <>
基本比较关键字:between...and and or not

SELECT * FROM teacher  WHERE id  = 1 --等于
SELECT * FROM teacher  WHERE id  != 1--不等于
SELECT * FROM teacher  WHERE id  <> 1--不等于
SELECT * FROM teacher  WHERE NOT id  = 1--不等于
SELECT * FROM teacher  WHERE  id  BETWEEN 0 AND 3-
SELECT * FROM teacher  WHERE  id  BETWEEN 0 AND 3 AND NAME LIKE '_老师'
SELECT * FROM teacher  WHERE  id  =1 OR NAME NOT LIKE '王%'

DQL data query language

基本查询

给字段取别名 t.id AS teacherid 可以省略as关键字

SELECT t.id  teacherid,  t.name tname, g.id gradeid, g.gradename  gradename
	FROM `teacher` t , `grade` g 
WHERE g.id = t.gradeid
=======聚合函数===============
SELECT `id`, CONCAT('name:',NAME) FROM teacher
SELECT CURRENT_DATE()
SELECT CURRENT_TIME()
SELECT CURRENT_TIMESTAMP()
=======去重,多用于子查询=======
SELECT DISTINCT `name` FROM teacher
=======模糊查询=================
is null  /like / between / in
SELECT * FROM `teacher` WHERE `name` IS NULL
SELECT * FROM `teacher` WHERE `id` BETWEEN 0 AND 3
SELECT * FROM `teacher` WHERE `gradeid` IN (1,2)
SELECT * FROM `teacher` WHERE `gradeid` IN (SELECT DISTINCT `id` FROM `grade`)
SELECT * FROM `teacher` WHERE `name` LIKE '%张%'
SELECT * FROM `teacher` WHERE `name` LIKE '_老师'
嵌套查询

创建新表 department(部门) employee(员工)

CREATE TABLE IF NOT EXISTS `department`(

	`deptId` INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '部门id',
	`deptName` VARCHAR(10) NOT NULL COMMENT '部门名称',
	`delete` TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除字段',
	`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入时间',
	`modify_time` DATETIME NOT NULL  DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间'
)ENGINE=INNODB CHARSET=utf8

CREATE TABLE IF NOT EXISTS `employee`(
	`id` INT(10) NOT NULL PRIMARY KEY COMMENT '员工id',
	`empName` VARCHAR(10) NOT NULL COMMENT '员工名称',
	`deptId` INT(10) COMMENT '部门id',
	`salary` INT(10) DEFAULT 1000 COMMENT '员工工资',
	`delete` TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除字段',
	`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入时间',
	`modify_time` DATETIME NOT NULL  DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间'
)ENGINE=INNODB CHARSET=utf8

INSERT INTO `department`(`deptName`) VALUES('部门一'),('部门二'),('部门三'),('部门四'),('部门五'),('部门六')
NSERT INTO `employee`(`id`,`empName`,`deptId`,`salary`) 
VALUES
(1001,'员工0',1,3000),
(1002,'员工1',1,3000),
(1003,'员工2',2,4000),
(1004,'员工3',3,5000),
(1005,'员工4',4,6000),
(1006,'员工5',5,7000),
(1007,'员工6',6,4000),
(1008,'员工7',1,8000),
(1009,'员工8',2,7000),
(1010,'员工9',3,6000),
(1011,'员工10',4,5000),
(1012,'员工11',5,1000),
(1013,'员工12',6,2000)

嵌套查询,将上一个表的查询结果作为下一个表的查询条件

例子:查询在部门一、部门二、和部门三的所有员工 员工表employee中没有部门名称只有部门id,所有得先查询部门id

SELECT * FROM `employee` 
	WHERE `deptid` IN(
	SELECT deptId FROM `department` 
		WHERE `deptName` IN 
		('部门一','部门二','部门三')
	)

当然实际开发中远远没有如此简单,可能配合聚合函数、多级嵌套以及联表查询。 这里其实有缺点,会发现得不到其他表的字段(部门名称),得配合联表查询

联表查询

接上一个例子,这样皆可以得到deptname

SELECT e.*, d.`deptname` FROM `employee` e, `department` d
	WHERE 
	e.`deptid` = d.`id`
	AND
	e.`deptid` IN(
	SELECT deptId FROM `department` 
		WHERE `deptName` IN 
		('部门一','部门二','部门三')
	)

下面四种联表查询,效果、结果完全一样。可互换

SELECT * FROM `employee`,`department`
SELECT * FROM `employee`   JOIN `department`
SELECT * FROM `employee`   CROSS JOIN `department`
SELECT * FROM `employee`  INNER JOIN `department`
inner join

inner join 需搭配on用于指定联表条件,即表之间怎么被联合,不然结果是  表1 × 表2

## 前表的deptid和后表的id相同
SELECT * FROM `employee` t1 INNER JOIN `department` t2
ON t1.`deptid` = t2.`deptId`
左连接 右连接

LEFT JOIN 时,右边表中不满足 ON或 USING 指定的条件时,会在结果中以 NULL 呈现。最终我们可以用where对结果过滤。

SELECT * FROM `employee` t1   LEFT JOIN `department` t2
ON t1.`deptid` = t2.`deptId`
## 使用using进行联表查询时,作为联表条件放在第一列且只出现一次
SELECT * FROM `employee` t1   LEFT JOIN `department` t2
USING(`deptId`)
##过滤nullSELECT * FROM `employee` t1   LEFT JOIN `department` t2
ON t1.`deptid` = t2.`deptId`
WHERE t2.`deptId` IS NOT NULL

RIGHT JOINLEFT JOIN类似,左边null填充。

NATURAL [LEFT] JOININNER JOINLEFT JOIN 配合使用了 USING 指定表中所有列的情况等效。

##这里创建时间不一样所以不显示
SELECT * FROM `employee`  NATURAL  JOIN `department` 

FUll OUTER JOIN MYSQL不支持,只有ORCAL支持。

##左表独有的(右表null填充)left join   右表独有的(左表null填充)right join  左右都有的 inner join  
SELECT * FROM `employee`  t1 LEFT JOIN `department` t2 ON t1.deptid=t2.deptid
 UNION 
SELECT * FROM `employee`  t1 RIGHT JOIN `department` t2 ON t1.deptid=t2.deptid

总结:

INNER JOIN 
JOIN
CROSS JOIN
=====
LEFT JOIN
RIGHT JOIN
NATURAL JOIN
==
FUll OUTER JOIN

onUSing区别: on展示所有列。USING合并对比列再展示。

通用sql模板

select [all | distinct(去重)]
	{* | table.* |[table.fieldl[as field1][,table.field2[as field2]][.......]]}
from table1....
	left/right/inner join tablename   on--判断
	where--条件
	group by --分组
 	having--过滤分组
    order by--排序
    limit     --分页  

-说明:
-where和having都是用于结果筛选。
-where直接从表中进行筛选,having是从查询1出来的结果进行过滤。
具体表现:where不能使用别名,having可以。

练习

-- 1.列出至少有一个员工的所有部门。
SELECT * FROM `department` dept 
INNER JOIN 
(SELECT `deptId` dpid , COUNT(`deptId`) `empnum` FROM `employee` 
GROUP BY `dpid`) t
ON dept.`deptid` = t.`dpid`
-- 2.列出薪金比"员工一"多的所有员工。
SELECT * FROM `employee`
WHERE	`salary` > 
(SELECT DISTINCT `salary` FROM `employee` 
WHERE `empName` = '员工1')

-- 8.列出在部门 "部门一" 工作的员工的姓名
SELECT * FROM `employee`
WHERE	`deptid` =
(SELECT deptid FROM `department` WHERE `deptname` = '部门一')
-- 9.列出薪金高于公司平均薪金的所有员工。
SELECT * FROM `employee` 
WHERE salary >
(SELECT AVG(salary) FROM `employee`)
-- 13.列出在每个部门工作的员工数量、平均工资。
SELECT * FROM `department` t1 
INNER JOIN(
SELECT `deptId`, COUNT(`id`) `empnum` FROM `employee` GROUP BY `deptId`
)t2 
USING(deptId)
INNER JOIN(
SELECT `deptId`, AVG(`salary`) `avgsalary` FROM `employee` GROUP BY `deptId`
)t3
USING(deptId)

-- 16.列出各部门的最低工资。
SELECT * FROM `department` t1 
INNER JOIN(
SELECT `deptId`, MIN(`salary`) `minsalary` FROM `employee` GROUP BY `deptId`
)t2 
USING(deptId)