数据库基础

课程概要

本单元目标

一、为什么要学习数据库

二、数据库的相关概念
DBMS、DB、SQL

三、数据库存储数据的特点

四、初始 MySQL
MySQL 产品的介绍
MySQL 产品的安装 ★
MySQL 服务的启动和停止 ★
MySQL 服务的登录和退出 ★
MySQL 的常见命令和语法规范

五、DQL 语言的学习 ★
基础查询 ★
条件查询 ★
排序查询 ★
常见函数 ★
分组函数 ★
分组查询 ★
连接查询 ★
子查询 √
分页查询 ★
union 联合查询 √

六、DML 语言的学习 ★
插入语句
修改语句
删除语句

七、DDL 语言的学习
库和表的管理 √
常见数据类型介绍 √
常见约束 √

八、TCL 语言的学习
事务和事务处理

九、视图的讲解 √
十、变量
十一、存储过程和函数
十二、流程控制结构

数据库的好处

1.持久化数据到本地
2.可以实现结构化查询,方便管理

数据库相关概念

1、DB:数据库,保存一组有组织的数据的容器
2、DBMS:数据库管理系统,又称为数据库软件(产品),用于管理 DB 中的数据
3、SQL:结构化查询语言,用于和 DBMS 通信的语言

数据库存储数据的特点

1、将数据放到表中,表再放到库中
2、一个数据库中可以有多个表,每个表都有一个的名字,用来标识自己。表名具有唯一性。
3、表具有一些特性,这些特性定义了数据在表中如何存储,类似 java 中 “类”的设计。
4、表由列组成,我们也称为字段。所有表都是由一个或多个列组成的,每一列类似 java 中的”属性”
5、表中的数据是按行存储的,每一行类似于 java 中的“对象”。

MySQL 安装和命令

MySQL 下载安装

window 平台下下载:https://dev.mysql.com/downloads/mysql/

MySQL 服务的启动和停止

  1. 方式一:计算机——右击管理——服务
  2. 方式二:通过管理员身份运行
  3. net start 服务名(启动服务)
  4. net stop 服务名(停止服务)

MySQL 服务的登录和退出

  1. 方式一:通过 mysql 自带的客户端
  2. 只限于 root 用户
  3. 方式二:通过windows自带的客户端
  4. 登录:
  5. mysql 【-h 主机名 -P 端口号 】-u用户名 -p密码
  6. mysql -h localhost -P 3306 -u root -pturbosoft
  7. 退出:
  8. exitctrl+C

MySQL 的常见命令

  1. # 1.查看当前所有的数据库
  2. show databases;
  3. # 2.打开指定的库
  4. use 库;
  5. # 3.查看当前库的所有表
  6. show tables;
  7. # 4.查看其它库的所有表
  8. show tables from 库名;
  9. # 5.查看当前所在的哪个库
  10. select database();
  11. # 6.创建表
  12. create table 表名(
  13. 列名 列类型,
  14. 列名 列类型,
  15. ...
  16. );
  17. # 7.查看表结构
  18. desc 表名;
  19. select * from 表名;
  20. # 8.查看服务器的版本
  21. # 方式一:登录到mysql服务端
  22. select version();
  23. # 方式二:没有登录到mysql服务端
  24. mysql --version
  25. // or
  26. mysql -V

基础演示脚本:

  1. mysql -u root -p
  2. show databases;
  3. use atguigu_mysql;
  4. select database();
  5. show tables;
  6. create table stu_info(
  7. id int,
  8. name varchar(20)
  9. );
  10. desc stu_info;
  11. insert stu_info (id,name) values(001,'john');
  12. select * from stu_info;
  13. update stu_info set name='rose' where id=1;
  14. delete from stu_info where id=1;

MySQL 的语法规范

  1. 不区分大小写,但建议关键字大写,表名、列名小写;
  2. 每条命令最好用分号结尾;
  3. 每条命令根据需要,可以进行缩进或换行;
  4. 注释;
  1. - 单行注释:#注释文字
  2. - 单行注释:-- 注释文字 (中间有个空格的)
  3. - 多行注释:/* 注释文字 * /

MySQL 的语言分类

  1. DQLData Query Language):数据查询语言
  2. select
  3. DML(Data Manipulate Language):数据操作语言
  4. insert updatedelete
  5. DDLData Define Languge):数据定义语言
  6. createdropalter
  7. TCLTransaction Control Language):事务控制语言
  8. commitrollback

MySQL 的常见命令(简介)

  1. # 查看所有的数据库
  2. show databases;
  3. # 打开指定 的库
  4. use 库名;
  5. #显示库中的所有表
  6. show tables;
  7. #显示指定库中的所有表
  8. show tables from 库名;
  9. #创建表
  10. create table 表名(
  11. 字段名 字段类型,
  12. 字段名 字段类型
  13. );
  14. #查看指定表的结构
  15. desc 表名;
  16. #显示表中的所有数据
  17. select * from 表名;

SQL 语言的学习

进阶 1:基础查询

  1. 语法:
  2. SELECT 查询列表 FROM 表名;
  3. 类似于Java :System.out.println(要打印的东西);
  4. 特点:
  5. 1.通过select查询完的结果 ,是一个虚拟的表格,不是真实存在
  6. 2.要查询的东西 可以是常量值、可以是表达式、可以是字段、可以是函数
  7. 起别名:(便于理解,如果要查询的字段有重名的情况,使用别名可以区分开来)
  8. 使用 AS , 或者 使用空格
  9. #方式一:使用AS
  10. SELECT last_name AS 姓,first_name AS FROM employees;
  11. #方式二:使用空格
  12. SELECT last_name 姓,first_name FROM employees;
  13. #案例:查询salary,显示结果为 out put
  14. SELECT salary AS "out put" FROM employees;
  15. 8.去重 DISTINCT
  16. #案例:查询员工表中涉及到的所有的部门编号
  17. SELECT DISTINCT department_id FROM employees;
  18. 9.字符串拼接
  19. #案例:查询员工名和姓连接成一个字段,并显示为 姓名
  20. SELECT CONCAT(first_name, last_name) AS 姓名 FROM employees;
  21. 10.特殊为null 情况下的处理
  22. # 如果为null 则处理为0
  23. SELECT IFNULL(commission_pct,0) AS 奖金率, commission_pct FROM employees;
  24. SELECT CONCAT(`first_name`,',',`last_name`,',',`job_id`,',',IFNULL(commission_pct,0)) AS out_put FROM employees;

进阶 2:条件查询

  1. 条件查询:根据条件过滤原始表的数据,查询到想要的数据
  2. 语法:
  3. SELECT
  4. 要查询的字段|表达式|常量值|函数
  5. FROM
  6. 表名
  7. WHERE
  8. 条件;
  9. 条件分类:
  10. 1.条件表达式筛选
  11. 示例:salary>10000
  12. 条件运算符:> < >= <= = != <>
  13. 2.逻辑表达式筛选
  14. 示例:salary>10000 && salary<20000
  15. 逻辑运算符:作用:用于连接条件表达式
  16. && || !
  17. AND OR NOT
  18. 逻辑运算符:
  19. AND(&&):两个条件如果同时成立,结果为true,否则为false
  20. OR(||):两个条件只要有一个成立,结果为true,否则为false
  21. NOT (!):如果条件成立,则not后为false,否则为true
  22. 3.模糊查询筛选
  23. 示例:last_name like 'a%'
  24. 运算符:
  25. LIKE
  26. BETWEEN AND
  27. IN
  28. IS NULL/ IS NOT NULL
  29. like
  30. 特点:一般和通配符搭配使用
  31. 通配符:% 任意多个字符,包含0个字符; _ 任意单个字符
  32. between and
  33. ①使用between and 可以提高语句的简洁度
  34. ②包含临界值
  35. ③两个临界值不要调换顺序
  36. in
  37. 含义:判断某字段的值是否属于in列表中的某一项
  38. 特点:
  39. ①使用in提高语句简洁度
  40. in列表的值类型必须一致或兼容
  41. in列表中不支持通配符
  42. is null
  43. =或<>不能用于判断null
  44. is nullis not null 可以判断null

查询语句案例:

  1. #一、按条件表达式筛选
  2. #案例1:查询工资>12000的员工信息
  3. SELECT * FROM employees WHERE salary>12000;
  4. #案例2:查询部门编号不等于90号的员工名和部门编号
  5. SELECT
  6. last_name,
  7. department_id
  8. FROM
  9. employees
  10. WHERE
  11. department_id<>90;
  12. #二、按逻辑表达式筛选
  13. #案例1:查询工资在10000到20000之间的员工名、工资以及奖金
  14. SELECT first_name,last_name, salary, commission_pct FROM employees WHERE salary>=10000 AND salary<=20000;
  15. #案例2:查询部门编号不是在90到110之间,或者工资高于15000的员工信息
  16. SELECT * FROM employees WHERE NOT(department_id>=90 AND department_id<=110) OR salary>15000;
  17. # 三、模糊查询
  18. #1.like
  19. #案例1:查询员工名中包含字符a的员工信息
  20. SELECT * FROM employees WHERE last_name LIKE '%a%';
  21. #案例2:查询员工名中第三个字符为e,第五个字符为a的员工名和工资
  22. SELECT first_name, last_name, salary FROM employees WHERE last_name LIKE '__n_l%';
  23. #案例3:查询员工名中第二个字符为_的员工名(转义)
  24. SELECT first_name, last_name FROM employees WHERE last_name LIKE '_\_%';
  25. SELECT first_name, last_name FROM employees WHERE last_name LIKE '_$_%' ESCAPE '$';
  26. #2.between and
  27. #案例1:查询员工编号在100到120之间的员工信息
  28. SELECT * FROM employees WHERE employee_id >= 100 AND employee_id<=120;
  29. # 等价于
  30. SELECT * FROM employees WHERE employee_id BETWEEN 100 AND 120;
  31. #3.in
  32. #案例:查询员工的工种编号是 IT_PROG、AD_VP、AD_PRES中的一个员工名和工种编号
  33. SELECT last_name, job_id FROM employees WHERE job_id = 'IT_PROT' OR job_id = 'AD_VP' OR JOB_ID ='AD_PRES';
  34. #等价于
  35. SELECT last_name, job_id FROM employees WHERE job_id IN( 'IT_PROT' ,'AD_VP','AD_PRES');
  36. #4、is null
  37. /*
  38. =或<>不能用于判断null值
  39. is null或is not null 可以判断null值
  40. */
  41. #案例1:查询没有奖金的员工名和奖金率
  42. SELECT last_name, commission_pct FROM employees WHERE commission_pct IS NOT NULL;
  43. #5.安全等于 <=>
  44. #案例1:查询没有奖金的员工名和奖金率
  45. SELECT last_name, commission_pct FROM employees WHERE commission_pct <=> NULL;
  46. #案例2:查询工资为12000的员工信息
  47. SELECT last_name, salary FROM employees WHERE salary <=> 12000;
  48. /*
  49. # IS NULL 和 <=>
  50. IS NULL: 仅仅可以判断NULL值,可读性较高,建议使用
  51. <=> : 既可以判断NULL值,又可以判断普通的数值,可读性较低
  52. */

进阶 3:排序查询

  1. 语法:
  2. SELECT
  3. 要查询的东西
  4. FROM
  5. WHERE
  6. 条件
  7. ORDER BY 排序的字段|表达式|函数|别名 ASC|DESC
  8. 特点:
  9. 1asc 代表的是升序,可以省略;desc代表的是降序
  10. 2order by 子句可以支持 单个字段、别名、表达式、函数、多个字段
  11. 3order by 子句在查询语句的最后面,除了limit子句

查询语句案例:

  1. #1、按单个字段排序
  2. SELECT * FROM employees ORDER BY salary DESC;
  3. #2、添加筛选条件再排序
  4. #案例:查询部门编号>=90的员工信息,并按员工编号降序
  5. SELECT *
  6. FROM employees
  7. WHERE department_id>=90
  8. ORDER BY employee_id DESC;
  9. #3、按表达式排序
  10. #案例:查询员工信息 按年薪降序
  11. SELECT *, salary*12*(1+IFNULL(commission_pct,0)) AS '年薪' FROM employees ORDER BY salary*12*(1+IFNULL(commission_pct,0)) DESC;
  12. #4、按别名排序
  13. #案例:查询员工信息 按年薪升序
  14. SELECT *, salary*12*(1+IFNULL(commission_pct,0)) 年薪 FROM employees ORDER BY 年薪 ASC;
  15. #5、按函数排序
  16. #案例:查询员工名,并且按名字的长度降序
  17. SELECT LENGTH(last_name), last_name
  18. FROM employees
  19. ORDER BY LENGTH(last_name) DESC;
  20. #6、按多个字段排序
  21. #案例:查询员工信息,要求先按工资降序,再按employee_id升序
  22. SELECT *
  23. FROM employees
  24. ORDER BY salary DESC, employee_id ASC;

进阶 4:常见函数

  1. 概念:类似于java的方法,将一组逻辑语句封装在方法体中,对外暴露方法名
  2. 好处:1、隐藏了实现细节 2、提高代码的重用性
  3. 调用:SELECT 函数名(实参列表) FROM 表】;
  4. 特点:①叫什么(函数名) ②干什么(函数功能)
  5. 分类:
  6. 1、单行函数
  7. concatlengthifnull
  8. 2、分组函数
  9. 功能:做统计使用,又称为统计函数、聚合函数、组函数
  10. 一、单行函数
  11. 1、字符函数
  12. concat 拼接
  13. substr 截取子串
  14. upper 转换成大写
  15. lower 转换成小写
  16. trim 去前后指定的空格和字符
  17. ltrim 去左边空格
  18. rtrim 去右边空格
  19. replace 替换
  20. lpad 左填充
  21. rpad 右填充
  22. instr 返回子串第一次出现的索引
  23. length 获取字节个数
  24. 2、数学函数
  25. round 四舍五入
  26. rand 随机数,返回0~1之间的小数
  27. floor 向下取整,返回<=该参数的最大整数
  28. ceil 向上取整向上取整,返回>=该参数的最小整数
  29. mod 取余
  30. truncate 截断
  31. 3、日期函数
  32. now 当前系统日期+时间
  33. year 当前年
  34. month 当前月
  35. day 当前日
  36. hour
  37. minute
  38. second
  39. datediff 返回两个日期相差的天数
  40. monthname 以英文形式返回月
  41. curdate 当前系统日期
  42. curtime 当前系统时间
  43. str_to_date 将字符转换成日期
  44. date_format 将日期转换成字符
  45. 4、流程控制函数
  46. if 处理双分支
  47. case 语句 处理多分支
  48. 情况1:处理等值判断
  49. 情况2:处理条件判断
  50. 5、其他函数
  51. version版本
  52. database当前库
  53. user当前连接用户
  54. password('字符')
  55. 二、分组函数
  56. sum 求和
  57. max 最大值
  58. min 最小值
  59. avg 平均值
  60. count 计数
  61. 特点:
  62. 1、以上五个分组函数都忽略null值,除了count(*)
  63. 2 sumavg一般用于处理数值型
  64. maxmincount可以处理任何数据类型
  65. 3、都可以搭配distinct使用,用于统计去重后的结果
  66. 4count的参数可以支持:
  67. 字段、* 、常量值,一般放1
  68. 建议使用 count(*)

查询语句案例:

  1. #一、字符函数
  2. #1.length 获取参数值的字节个数
  3. SELECT LENGTH('john');
  4. SELECT LENGTH('张三丰hahaha');
  5. SHOW VARIABLES LIKE '%char%';
  6. #2.concat 拼接字符串
  7. SELECT CONCAT(last_name,'_',first_name) 姓名 FROM employees;
  8. #3.upper、lower
  9. SELECT UPPER('john');
  10. SELECT LOWER('joHn');
  11. #示例:将姓变大写,名变小写,然后拼接
  12. SELECT CONCAT(UPPER(last_name),LOWER(first_name)) 姓名 FROM employees;
  13. #4.substr、substring
  14. #注意:索引从1开始
  15. #截取从指定索引处后面所有字符
  16. SELECT SUBSTR('李莫愁爱上了陆展元',7) out_put;
  17. #截取从指定索引处指定字符长度的字符
  18. SELECT SUBSTR('李莫愁爱上了陆展元',1,3) AS out_put;
  19. #案例:姓名中首字符大写,其他字符小写然后用_拼接,显示出来
  20. SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),'_', LOWER(SUBSTR(last_name,2))) AS out_put FROM employees;
  21. #5.instr 返回子串第一次出现的索引,如果找不到返回0
  22. SELECT INSTR('杨不殷悔爱上了殷六侠','殷六侠') AS out_put;
  23. #6.trim
  24. SELECT LENGTH(TRIM(' 张翠山 ')) AS out_put;
  25. SELECT TRIM('aa' FROM 'aaaaaaaaa张aaaaaaaaaaaa翠山aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') AS out_put;
  26. #7.lpad 用指定的字符实现左填充指定长度
  27. SELECT LPAD('殷素素',10,'*') AS out_put;
  28. SELECT LPAD('殷素素',2,'*') AS out_put;
  29. #8.rpad 用指定的字符实现右填充指定长度
  30. SELECT RPAD('殷素素',12,'ab') AS out_put;
  31. #9.replace 替换
  32. SELECT REPLACE('周芷若周芷若周芷若周芷若张无忌爱上了周芷若','周芷若','赵敏') AS out_put;
  33. -- SELECT REPLACE(str,from_str,to_str)
  34. #二、数学函数
  35. #round 四舍五入
  36. SELECT ROUND(-1.55);
  37. SELECT ROUND(1.567,2);
  38. #ceil 向上取整,返回>=该参数的最小整数
  39. SELECT CEIL(-1.02);
  40. #floor 向下取整,返回<=该参数的最大整数
  41. SELECT FLOOR(-9.99);
  42. #truncate 截断
  43. SELECT TRUNCATE(1.69999,2);
  44. #mod取余
  45. /*
  46. mod(a,b) : a-a/b*b
  47. mod(-10,-3):-10- (-10)/(-3)*(-3)=-1
  48. */
  49. SELECT MOD(10,-3);
  50. SELECT 10%3;
  51. #三、日期函数
  52. #now 返回当前系统日期+时间
  53. SELECT NOW();
  54. #curdate 返回当前系统日期,不包含时间
  55. SELECT CURDATE();
  56. #curtime 返回当前时间,不包含日期
  57. SELECT CURTIME();
  58. #可以获取指定的部分,年、月、日、小时、分钟、秒
  59. SELECT YEAR(NOW()) 年;
  60. SELECT YEAR('1998-1-1') 年;
  61. SELECT YEAR(hiredate) FROM employees;
  62. SELECT MONTH(NOW()) 月;
  63. SELECT MONTHNAME(NOW()) 月;
  64. #str_to_date 将字符通过指定的格式转换成日期
  65. SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d') AS out_put;
  66. #查询入职日期为1992-4-3的员工信息
  67. SELECT * FROM employees WHERE hiredate = '1992-4-3';
  68. SELECT * FROM employees WHERE hiredate = STR_TO_DATE('4-3 1992','%c-%d %Y');
  69. #date_format 将日期转换成字符
  70. SELECT DATE_FORMAT(NOW(),'%y年%m月%d日') AS out_put;
  71. #查询有奖金的员工名和入职日期(xx月/xx日 xx年)
  72. SELECT last_name,DATE_FORMAT(hiredate,'%m月/%d日 %Y年') 入职日期
  73. FROM employees
  74. WHERE commission_pct IS NOT NULL;
  75. #四、其他函数
  76. SELECT VERSION();
  77. SELECT DATABASE();
  78. SELECT USER();
  79. #五、流程控制函数
  80. #1.if函数: if else 的效果
  81. SELECT IF(10<5,'大','小') RESULT;
  82. SELECT last_name, commission_pct, IF(commission_pct IS NULL,'没奖金,呵呵','有奖金,嘻嘻') 备注
  83. FROM employees;
  84. #2.case函数的使用一: switch case 的效果
  85. /*
  86. java中
  87. switch(变量或表达式){
  88. case 常量1:语句1;break;
  89. ...
  90. default:语句n;break;
  91. }
  92. mysql中
  93. case 要判断的字段或表达式
  94. when 常量1 then 要显示的值1或语句1;
  95. when 常量2 then 要显示的值2或语句2;
  96. ...
  97. else 要显示的值n或语句n;
  98. end
  99. */
  100. /*案例:查询员工的工资,要求
  101. 部门号=30,显示的工资为1.1倍
  102. 部门号=40,显示的工资为1.2倍
  103. 部门号=50,显示的工资为1.3倍
  104. 其他部门,显示的工资为原工资
  105. */
  106. SELECT salary 原始工资,department_id,
  107. CASE department_id
  108. WHEN 30 THEN salary*1.1
  109. WHEN 40 THEN salary*1.2
  110. WHEN 50 THEN salary*1.3
  111. ELSE salary
  112. END AS 新工资
  113. FROM employees;
  114. #3.case 函数的使用二:类似于 多重if
  115. /*
  116. java中:
  117. if(条件1){
  118. 语句1;
  119. }else if(条件2){
  120. 语句2;
  121. }
  122. ...
  123. else{
  124. 语句n;
  125. }
  126. mysql中:
  127. case
  128. when 条件1 then 要显示的值1或语句1
  129. when 条件2 then 要显示的值2或语句2
  130. 。。。
  131. else 要显示的值n或语句n
  132. end
  133. */
  134. #案例:查询员工的工资的情况
  135. 如果工资>20000,显示A级别
  136. 如果工资>15000,显示B级别
  137. 如果工资>10000,显示C级别
  138. 否则,显示D级别
  139. SELECT salary,
  140. CASE
  141. WHEN salary>20000 THEN 'A'
  142. WHEN salary>15000 THEN 'B'
  143. WHEN salary>10000 THEN 'C'
  144. ELSE 'D'
  145. END AS 工资级别
  146. FROM employees;

进阶 4:分组函数

  1. /*
  2. 功能:用作统计使用,又称为聚合函数或统计函数或组函数
  3. 分类:
  4. sum 求和、avg 平均值、max 最大值 、min 最小值 、count 计算个数
  5. 特点:
  6. 1、sum、avg一般用于处理数值型
  7. max、min、count可以处理任何类型
  8. 2、以上分组函数都忽略null值
  9. 3、可以和distinct搭配实现去重的运算
  10. 4、count函数的单独介绍
  11. 一般使用count(*)用作统计行数
  12. 5、和分组函数一同查询的字段要求是group by后的字段
  13. */
  14. #1、简单 的使用
  15. SELECT SUM(salary) FROM employees;
  16. SELECT AVG(salary) FROM employees;
  17. SELECT MIN(salary) FROM employees;
  18. SELECT MAX(salary) FROM employees;
  19. SELECT COUNT(salary) FROM employees;
  20. SELECT SUM(salary) 和, AVG(salary) 平均, MAX(salary) 最高, MIN(salary) 最低, COUNT(salary) 个数
  21. FROM employees;
  22. SELECT SUM(salary) 和, ROUND(AVG(salary),2) 平均, MAX(salary) 最高, MIN(salary) 最低, COUNT(salary) 个数
  23. FROM employees;
  24. #2、参数支持哪些类型
  25. SELECT SUM(last_name) ,AVG(last_name) FROM employees; # 适用于数值类型
  26. SELECT SUM(hiredate) ,AVG(hiredate) FROM employees;
  27. SELECT MAX(last_name),MIN(last_name) FROM employees;
  28. SELECT MAX(hiredate),MIN(hiredate) FROM employees;
  29. SELECT COUNT(commission_pct) FROM employees; # 计算非空的个数
  30. SELECT COUNT(last_name) FROM employees;
  31. #3、是否忽略null
  32. SELECT SUM(commission_pct), AVG(commission_pct), SUM(commission_pct)/35, SUM(commission_pct)/107 FROM employees;
  33. SELECT MAX(commission_pct), MIN(commission_pct) FROM employees;
  34. SELECT COUNT(commission_pct) FROM employees;
  35. SELECT commission_pct FROM employees;
  36. #4、和distinct搭配
  37. SELECT SUM(DISTINCT salary), SUM(salary) FROM employees;
  38. SELECT COUNT(DISTINCT salary), COUNT(salary) FROM employees;
  39. #5、count函数的详细介绍
  40. SELECT COUNT(salary) FROM employees;
  41. SELECT COUNT(*) FROM employees;
  42. SELECT COUNT(1) FROM employees;
  43. 效率:
  44. MYISAM存储引擎下 COUNT(*)的效率高
  45. INNODB存储引擎下,COUNT(*)和COUNT(1)的效率差不多,比COUNT(字段)要高一些
  46. #6、和分组函数一同查询的字段有限制,要求是 group by 出现的字段
  47. SELECT AVG(salary), employee_id FROM employees;

进阶 5:分组查询

  1. 语法:
  2. SELECT 查询的字段,分组函数
  3. FROM
  4. [WHERE 筛选条件]
  5. GROUP BY 分组的字段
  6. [HAVING 分组后的筛选]
  7. [ORDER BY 排序列表]
  8. 说明: WHERE 一定要在 FROM 后边
  9. 特点:
  10. 1、分组筛选
  11. 针对的表 位置 使用关键字
  12. 分组前筛选: 原始表 GROUP BY的前面 WHERE
  13. 分组后筛选: 分组后的结果集 GROUP BY的后面 HAVING
  14. 1)分组函数做条件肯定是放在 HAVING 子句中;
  15. 2)能用分组前筛选就优先使用分组前筛选
  16. 2GROUP BY 子句支持单个字段分组、多个字段分组(多个字段之间用逗号分隔没有顺序要求),表达式或者函数(用的较少)
  17. 3、也可以添加排序(排序放在整个分组查询的最后)
  18. 4、和分组函数一同查询的字段最好是分组后的字段
  19. 5HAVING 后可以支持别名

查询语句案例:

  1. # 引入:查询每个部门的平均工资
  2. SELECT AVG(salary) FROM employees;
  3. # 简单的分组查询
  4. # 案例1:查询每个工种的最高工资
  5. SELECT MAX(salary),job_id FROM employees GROUP BY job_id;
  6. # 案例2:查询每个位置上的部门个数
  7. SELECT COUNT(*),location_id FROM departments GROUP BY location_id;
  8. #添加筛选条件(分组前)
  9. # 案例1:查询邮箱中包含a字符的,每个部门的平均工资
  10. SELECT AVG(salary),department_id
  11. FROM employees
  12. WHERE email LIKE '%a%'
  13. GROUP BY department_id;
  14. # 案例2:查询有奖金的每个领导手下员工的最高工资
  15. SELECT MAX(salary),manager_id
  16. FROM employees
  17. WHERE commission_pct IS NOT NULL
  18. GROUP BY manager_id;
  19. #添加复杂筛选条件(分组后)
  20. # 案例1:查询哪个部门的员工个数大于2
  21. #(1)查询每个部门的员工个数
  22. SELECT COUNT(*),department_id
  23. FROM employees
  24. GROUP BY department_id;
  25. #(2) 根据(1)的结果进行筛选,查询哪个部门的员工个数大于2
  26. SELECT COUNT(*),department_id
  27. FROM employees
  28. GROUP BY department_id
  29. HAVING COUNT(*) > 2;
  30. #案例2:查询每个工种有奖金的员工,且最高工资大于12000的工种编号和最高工资
  31. #(1)查询每个工种的有奖金的员工的最高工资
  32. SELECT MAX(salary),job_id
  33. FROM employees
  34. WHERE commission_pct IS NOT NULL
  35. GROUP BY job_id;
  36. #(2) 根据(1)的结果进行筛选,最高工资大于12000
  37. SELECT MAX(salary),job_id
  38. FROM employees
  39. WHERE commission_pct IS NOT NULL
  40. GROUP BY job_id
  41. HAVING MAX(salary) > 12000;
  42. #案例2:查询领导编号>102的每个领导手底下最低工资>5000的领导编号是哪个,及最低工资
  43. #(1)查询领导编号>102的每个领导手底下最低工资
  44. SELECT MIN(salary),manager_id
  45. FROM employees
  46. GROUP BY manager_id;
  47. #(2) 添加筛选条件:编号大于102
  48. SELECT MIN(salary),manager_id
  49. FROM employees
  50. WHERE manager_id > 102
  51. GROUP BY manager_id;
  52. #(2) 添加筛选条件:最低工资大于5000
  53. SELECT MIN(salary),manager_id
  54. FROM employees
  55. WHERE manager_id > 102
  56. GROUP BY manager_id
  57. HAVING MIN(salary) > 5000;
  58. # 按表达式分组
  59. #案例1:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数大于5的有哪些
  60. #(1)查询每个长度的员工个数
  61. SELECT COUNT(*),LENGTH(last_name) AS len_name
  62. FROM employees
  63. GROUP BY LENGTH(last_name);
  64. #(2) 添加筛选条件:筛选员工个数大于5
  65. SELECT COUNT(*),LENGTH(last_name) AS len_name
  66. FROM employees
  67. GROUP BY LENGTH(last_name)
  68. HAVING COUNT(*) > 5;
  69. #支持别名(不常用)
  70. SELECT COUNT(*) c,LENGTH(last_name) AS len_name
  71. FROM employees
  72. GROUP BY len_name
  73. HAVING c > 5;
  74. # 按多个字段分组
  75. #案例1:查询每个部门每个工种的员工的平均工资
  76. SELECT AVG(salary),department_id,job_id
  77. FROM employees
  78. GROUP BY department_id,job_id;
  79. # 添加排序
  80. #案例1:查询每个部门每个工种的员工的平均工资,并按照平均工资的高低显示
  81. SELECT AVG(salary),department_id,job_id
  82. FROM employees
  83. GROUP BY department_id,job_id
  84. ORDER BY AVG(salary) DESC;
  85. # 再加:department_id 不为null
  86. SELECT AVG(salary),department_id,job_id
  87. FROM employees
  88. WHERE department_id IS NOT NULL
  89. GROUP BY department_id,job_id
  90. ORDER BY AVG(salary) DESC;
  91. # 再加:平均工资大于10000
  92. SELECT AVG(salary),department_id,job_id
  93. FROM employees
  94. WHERE department_id IS NOT NULL
  95. GROUP BY department_id,job_id
  96. HAVING AVG(salary) > 10000
  97. ORDER BY AVG(salary) DESC;

进阶 6:连接查询

  1. 含义:又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
  2. 笛卡尔乘积:如果连接条件省略或无效则会出现
  3. 解决办法:添加上连接条件
  4. 分类:
  5. 按年代分类:
  6. sql92标准:仅仅支持内连接
  7. sql99标准【推荐】:支持内连接+外连接(左外和右外)+交叉连接
  8. 按功能分类:
  9. 内连接:
  10. 等值连接
  11. 非等值连接
  12. 自连接
  13. 外连接:
  14. 左外连接
  15. 右外连接
  16. 全外连接
  17. 交叉连接:
  18. # 等值连接
  19. 语法:
  20. select 查询列表
  21. from 1 别名,表2 别名
  22. where 1.key=表2.key
  23. and 筛选条件】
  24. group by 分组字段】
  25. having 分组后的筛选】
  26. order by 排序字段】
  27. 特点:
  28. 多表等值连接的结果为多表的交集部分
  29. n表连接,至少需要n-1个连接条件
  30. 多表的顺序没有要求
  31. 一般需要为表起别名
  32. 可以搭配前面介绍的所有子句使用,比如排序、分组、筛选

查询语句案例:

  1. # 场景引入
  2. show databases;
  3. use girls;
  4. SELECT * FROM beauty;
  5. SELECT * FROM boys;
  6. SELECT NAME,boyName FROM boys,beauty
  7. WHERE beauty.boyfriend_id = boys.id;
  8. USE myemployees;
  9. #一、sql92标准
  10. #1、等值连接
  11. /*
  12. 语法:
  13. select 查询列表
  14. from 表1 别名,表2 别名
  15. where 表1.key = 表2.key
  16. 【and 筛选条件】
  17. 【and 筛选条件】
  18. 【and 筛选条件】
  19. 特点:
  20. ① 多表等值连接的结果为多表的交集部分
  21. ② n表连接,至少需要n-1个连接条件
  22. ③ 多表的顺序没有要求
  23. ④ 一般需要为表起别名
  24. ⑤ 可以搭配前面介绍的所有子句使用,比如排序、分组、筛选
  25. */
  26. #案例1:查询女神名和对应的男神名
  27. SELECT NAME,boyName
  28. FROM boys,beauty
  29. WHERE beauty.boyfriend_id = boys.id;
  30. #案例2:查询员工名和对应的部门名
  31. SELECT last_name,department_name
  32. FROM employees,departments
  33. WHERE employees.department_id = departments.department_id;
  34. #2、为表起别名
  35. /*
  36. ①提高语句的简洁度
  37. ②区分多个重名的字段
  38. 注意:如果为表起了别名,则查询的字段就不能使用原来的表名去限定
  39. */
  40. #查询员工名、工种号、工种名
  41. SELECT last_name,employees.job_id,job_title
  42. FROM employees,jobs
  43. WHERE employees.`job_id`=jobs.`job_id`;
  44. SELECT e.last_name,e.job_id,j.job_title
  45. FROM employees AS e,jobs j
  46. WHERE e.`job_id`=j.`job_id`;
  47. #3、两个表的顺序是否可以调换
  48. #查询员工名、工种号、工种名
  49. SELECT e.last_name,e.job_id,j.job_title
  50. FROM jobs j,employees e
  51. WHERE e.`job_id`=j.`job_id`;
  52. #4、可以加筛选
  53. #案例1:查询有奖金的员工名、部门名
  54. SELECT last_name,department_name,commission_pct
  55. FROM employees e,departments d
  56. WHERE e.department_id = d.department_id
  57. AND e.commission_pct IS NOT NULL;
  58. #案例2:查询城市名中第二个字符为o的部门名和城市名
  59. SELECT department_name,city
  60. FROM departments d, locations l
  61. WHERE d.location_id = l.location_id
  62. AND city LIKE '_o%';
  63. #5、可以加分组
  64. #案例1:查询每个城市的部门个数
  65. SELECT COUNT(*) 个数,city
  66. FROM departments d,locations l
  67. WHERE d.location_id = l.location_id
  68. GROUP BY city;
  69. #案例2:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资
  70. SELECT department_name,d.manager_id,MIN(salary)
  71. FROM departments d,employees e
  72. WHERE d.department_id = e.department_id
  73. AND commission_pct IS NOT NULL
  74. GROUP BY department_name,d.manager_id;
  75. SELECT department_name,MIN(salary)
  76. FROM departments d,employees e
  77. WHERE d.department_id = e.department_id
  78. AND commission_pct IS NOT NULL
  79. GROUP BY department_name;
  80. #6、可以加排序
  81. #案例:查询每个工种的工种名和员工的个数,并且按员工个数降序
  82. SELECT job_title,COUNT(*)
  83. FROM employees e,jobs j
  84. WHERE e.job_id=j.job_id
  85. GROUP BY job_title
  86. ORDER BY COUNT(*) DESC;
  87. #7、可以实现三表连接
  88. #案例:查询员工名、部门名和所在的城市
  89. SELECT last_name,department_name,city
  90. FROM employees e,departments d,locations l
  91. WHERE e.department_id=d.department_id
  92. AND d.location_id=l.location_id
  93. AND city LIKE 's%'
  94. ORDER BY department_name DESC;
  95. #2、非等值连接
  96. #案例1:查询员工的工资和工资级别
  97. SELECT salary,grade_level
  98. FROM employees e,job_grades g
  99. WHERE salary BETWEEN g.lowest_sal AND g.highest_sal
  100. AND g.grade_level = 'A';
  101. /*
  102. select salary,employee_id from employees;
  103. select * from job_grades;
  104. CREATE TABLE job_grades
  105. (grade_level VARCHAR(3),
  106. lowest_sal int,
  107. highest_sal int);
  108. INSERT INTO job_grades
  109. VALUES ('A', 1000, 2999);
  110. INSERT INTO job_grades
  111. VALUES ('B', 3000, 5999);
  112. INSERT INTO job_grades
  113. VALUES('C', 6000, 9999);
  114. INSERT INTO job_grades
  115. VALUES('D', 10000, 14999);
  116. INSERT INTO job_grades
  117. VALUES('E', 15000, 24999);
  118. INSERT INTO job_grades
  119. VALUES('F', 25000, 40000);
  120. */
  121. #3、自连接
  122. #案例:查询 员工名和上级的名称
  123. SELECT e.employee_id,e.last_name,m.employee_id,m.last_name
  124. FROM employees e,employees m
  125. WHERE e.manager_id = m.employee_id;

进阶 6:连接查询(sql99语法)

  1. #二、sql99语法
  2. /*
  3. 语法:
  4. select 查询列表
  5. from 1 别名 【连接类型】
  6. join 2 别名
  7. on 连接条件
  8. where 筛选条件】
  9. group by 分组】
  10. having 筛选条件】
  11. order by 排序列表】
  12. 连接类型分类:
  13. 内连接(★):inner
  14. 外连接
  15. 左外(★):left outer
  16. 右外(★):right outer
  17. 全外:fullouter
  18. 交叉连接:cross
  19. */

查询语句案例:

  1. #二、sql99语法
  2. /*
  3. 语法:
  4. select 查询列表
  5. from 表1 别名 【连接类型】
  6. join 表2 别名
  7. on 连接条件
  8. 【where 筛选条件】
  9. 【group by 分组】
  10. 【having 筛选条件】
  11. 【order by 排序列表】
  12. 连接类型分类:
  13. 内连接(★):inner
  14. 外连接
  15. 左外(★):left 【outer】
  16. 右外(★):right 【outer】
  17. 全外:full【outer】
  18. 交叉连接:cross
  19. */
  20. #一)内连接
  21. /*
  22. 语法:
  23. select 查询列表
  24. from 表1 别名
  25. inner join 表2 别名
  26. on 连接条件;
  27. 分类:
  28. 等值
  29. 非等值
  30. 自连接
  31. 特点:
  32. ① 添加排序、分组、筛选
  33. ② inner可以省略
  34. ③ 筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
  35. ④ inner join连接和sql92语法中的等值连接效果是一样的,都是查询多表的交集
  36. */
  37. #1、等值连接
  38. #案例1.查询员工名、部门名
  39. SELECT last_name,department_name
  40. FROM departments d
  41. INNER JOIN employees e
  42. ON e.`department_id` = d.`department_id`;
  43. #案例2.查询名字中包含e的员工名和工种名(添加筛选)
  44. SELECT last_name,job_title
  45. FROM employees e
  46. INNER JOIN jobs j
  47. ON e.job_id = j.job_id
  48. WHERE e.last_name LIKE '%e%';
  49. #3. 查询部门个数>3的城市名和部门个数,(添加分组+筛选)
  50. #①查询每个城市的部门个数
  51. #②在①结果上筛选满足条件的
  52. SELECT city,COUNT(*) 部门个数
  53. FROM departments d
  54. INNER JOIN locations l
  55. ON d.location_id=l.location_id
  56. GROUP BY city
  57. HAVING COUNT(*)>3;
  58. #案例4.查询哪个部门的员工个数>3的部门名和员工个数,并按个数降序(添加排序)
  59. #①查询每个部门的员工个数
  60. SELECT COUNT(*),department_name
  61. FROM employees e
  62. INNER JOIN departments d
  63. ON e.`department_id`=d.`department_id`
  64. GROUP BY department_name;
  65. #② 在①结果上筛选员工个数>3的记录,并排序
  66. SELECT COUNT(*) 个数,department_name
  67. FROM employees e
  68. INNER JOIN departments d
  69. ON e.`department_id`=d.`department_id`
  70. GROUP BY department_name
  71. HAVING COUNT(*)>3
  72. ORDER BY COUNT(*) DESC;
  73. #5.查询员工名、部门名、工种名,并按部门名降序(添加三表连接)
  74. SELECT last_name,department_name,job_title
  75. FROM employees e
  76. INNER JOIN departments d ON e.`department_id`=d.`department_id`
  77. INNER JOIN jobs j ON e.`job_id` = j.`job_id`
  78. ORDER BY department_name DESC;
  79. #2、非等值连接
  80. #查询员工的工资级别
  81. SELECT salary,grade_level
  82. FROM employees e
  83. INNER JOIN job_grades g
  84. ON e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`;
  85. #查询工资级别的个数>20的个数,并且按工资级别降序
  86. SELECT COUNT(*),grade_level
  87. FROM employees e
  88. JOIN job_grades g
  89. ON e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`
  90. GROUP BY grade_level
  91. HAVING COUNT(*)>20
  92. ORDER BY grade_level DESC;
  93. #3、自连接
  94. #查询员工的名字、上级的名字
  95. SELECT e.last_name,m.last_name '上级'
  96. FROM employees e
  97. INNER JOIN employees m
  98. ON e.`manager_id`= m.`employee_id`;
  99. #查询姓名中包含字符k的员工的名字、上级的名字
  100. SELECT e.last_name,m.last_name
  101. FROM employees e
  102. JOIN employees m
  103. ON e.`manager_id`= m.`employee_id`
  104. WHERE e.`last_name` LIKE '%k%';
  105. #二、外连接
  106. /*
  107. 应用场景:用于查询一个表中有,另一个表没有的记录
  108. 特点:
  109. 1、外连接的查询结果为主表中的所有记录
  110. 如果从表中有和它匹配的,则显示匹配的值
  111. 如果从表中没有和它匹配的,则显示null
  112. 外连接查询结果=内连接结果+主表中有而从表没有的记录
  113. 2、左外连接,left join左边的是主表
  114. 右外连接,right join右边的是主表
  115. 3、左外和右外交换两个表的顺序,可以实现同样的效果
  116. 4、全外连接=内连接的结果+表1中有但表2没有的+表2中有但表1没有的
  117. */
  118. #引入:查询男朋友 不在男神表的的女神名
  119. use girls;
  120. SELECT * FROM beauty;
  121. SELECT * FROM boys;
  122. #左外连接
  123. SELECT b.name,bo.*
  124. FROM beauty b
  125. LEFT OUTER JOIN boys bo
  126. ON b.`boyfriend_id` = bo.`id`
  127. WHERE bo.`id` IS NULL;
  128. #右外连接
  129. SELECT b.name,bo.*
  130. FROM boys bo
  131. RIGHT OUTER JOIN beauty b
  132. ON b.`boyfriend_id` = bo.`id`
  133. WHERE bo.`id` IS NULL;
  134. #左外连接
  135. SELECT b.*,bo.*
  136. FROM boys bo
  137. LEFT OUTER JOIN beauty b
  138. ON b.`boyfriend_id` = bo.`id`
  139. WHERE bo.`id` IS NULL;
  140. #案例1:查询哪个部门没有员工(部门为主表)
  141. USE myemployees;
  142. #左外
  143. SELECT d.*,e.employee_id
  144. FROM departments d
  145. LEFT OUTER JOIN employees e
  146. ON d.`department_id` = e.`department_id`
  147. WHERE e.`employee_id` IS NULL;
  148. #右外
  149. SELECT d.*,e.employee_id
  150. FROM employees e
  151. RIGHT OUTER JOIN departments d
  152. ON d.`department_id` = e.`department_id`
  153. WHERE e.`employee_id` IS NULL;
  154. #全外
  155. USE girls;
  156. #(报错)
  157. SELECT b.*,bo.*
  158. FROM beauty b
  159. FULL OUTER JOIN boys bo
  160. ON b.`boyfriend_id` = bo.id;
  161. #交叉连接
  162. SELECT b.*,bo.*
  163. FROM beauty b
  164. CROSS JOIN boys bo;
  165. #sql92和 sql99pk
  166. /*
  167. 功能:sql99支持的较多
  168. 可读性:sql99实现连接条件和筛选条件的分离,可读性较高
  169. */

join 连接总结
MySQL基础[尚硅谷] - 图1
MySQL基础[尚硅谷] - 图2

进阶 7:子查询

  1. 含义:
  2. 一条查询语句中又嵌套了另一条完整的select语句,其中被嵌套的select语句,称为子查询或内查询
  3. 在外面的查询语句,称为主查询或外查询
  4. 分类:
  5. 1.按子查询出现的位置:
  6. select后面:
  7. 仅仅支持标量子查询
  8. from后面:
  9. 支持表子查询
  10. wherehaving后面:★
  11. 标量子查询(单行)
  12. 列子查询 (多行)
  13. 行子查询
  14. exists后面(相关子查询)
  15. 表子查询
  16. 2.按结果集的行列数不同:
  17. 标量子查询(结果集只有一行一列)
  18. 列子查询(结果集只有一列多行)
  19. 行子查询(结果集有一行多列)
  20. 表子查询(结果集一般为多行多列)
  21. 特点:
  22. 1、子查询都放在小括号内
  23. 2、子查询可以放在from后面、select后面、where后面、having后面,但一般放在条件的右侧
  24. 3、子查询优先于主查询执行,主查询使用了子查询的执行结果
  25. 4、子查询根据查询结果的行数不同分为以下两类:
  26. 单行子查询
  27. 结果集只有一行
  28. 一般搭配单行操作符使用:> < = <> >= <=
  29. 非法使用子查询的情况:
  30. a、子查询的结果为一组值
  31. b、子查询的结果为空
  32. 多行子查询
  33. 结果集有多行
  34. 一般搭配多行操作符使用:anyallinnot in
  35. in 属于子查询结果中的任意一个就行
  36. anyall往往可以用其他查询代替

查询语句案例:

  1. #一、where或having后面
  2. /*
  3. 1、标量子查询(单行子查询)
  4. 2、列子查询(多行子查询)
  5. 3、行子查询(多列多行)
  6. 特点:
  7. ①子查询放在小括号内
  8. ②子查询一般放在条件的右侧
  9. ③标量子查询,一般搭配着单行操作符使用
  10. > < >= <= = <>
  11. 列子查询,一般搭配着多行操作符使用
  12. in/not in、any/some、all
  13. ④子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果
  14. */
  15. #1.标量子查询★
  16. #案例1:谁的工资比 Abel 高?
  17. #①查询Abel的工资
  18. SELECT salary
  19. FROM employees
  20. WHERE last_name = 'Abel';
  21. #②查询员工的信息,满足 salary>①结果
  22. SELECT *
  23. FROM employees
  24. WHERE salary >(
  25. SELECT salary
  26. FROM employees
  27. WHERE last_name = 'Abel'
  28. );
  29. #案例2:返回job_id与141号员工相同,salary比143号员工多的员工 姓名,job_id 和工资
  30. #①查询141号员工的job_id
  31. SELECT job_id
  32. FROM employees
  33. WHERE employee_id = 141
  34. #②查询143号员工的salary
  35. SELECT salary
  36. FROM employees
  37. WHERE employee_id = 143
  38. #③查询员工的姓名,job_id 和工资,要求job_id=①并且salary>②
  39. SELECT last_name,job_id,salary
  40. FROM employees
  41. WHERE job_id = (
  42. SELECT job_id
  43. FROM employees
  44. WHERE employee_id = 141
  45. ) AND salary>(
  46. SELECT salary
  47. FROM employees
  48. WHERE employee_id = 143
  49. );
  50. #案例3:返回公司工资最少的员工的last_name,job_id和salary
  51. #①查询公司的 最低工资
  52. SELECT MIN(salary)
  53. FROM employees
  54. #②查询last_name,job_id和salary,要求salary=①
  55. SELECT last_name,job_id,salary
  56. FROM employees
  57. WHERE salary=(
  58. SELECT MIN(salary)
  59. FROM employees
  60. );
  61. #案例4:查询最低工资大于50号部门最低工资的部门id和其最低工资
  62. #①查询50号部门的最低工资
  63. SELECT MIN(salary)
  64. FROM employees
  65. WHERE department_id = 50
  66. #②查询每个部门的最低工资
  67. SELECT MIN(salary),department_id
  68. FROM employees
  69. GROUP BY department_id
  70. #③ 在②基础上筛选,满足min(salary)>①
  71. SELECT MIN(salary),department_id
  72. FROM employees
  73. GROUP BY department_id
  74. HAVING MIN(salary)>(
  75. SELECT MIN(salary)
  76. FROM employees
  77. WHERE department_id = 50
  78. );
  79. #非法使用标量子查询(子查询结果不是一行一列 警告)
  80. SELECT MIN(salary),department_id
  81. FROM employees
  82. GROUP BY department_id
  83. HAVING MIN(salary)>(
  84. SELECT salary
  85. FROM employees
  86. WHERE department_id = 250
  87. );
  88. #2.列子查询(多行子查询)★
  89. #案例1:返回location_id是1400或1700的部门中的所有员工姓名
  90. #①查询location_id是1400或1700的部门编号
  91. SELECT DISTINCT department_id,location_id
  92. FROM departments
  93. WHERE location_id IN(1400,1700)
  94. #②查询员工姓名,要求部门号是①列表中的某一个
  95. SELECT last_name
  96. FROM employees
  97. WHERE department_id <>ALL(
  98. SELECT DISTINCT department_id
  99. FROM departments
  100. WHERE location_id IN(1400,1700)
  101. );
  102. #或
  103. SELECT last_name
  104. FROM employees
  105. WHERE department_id NOT IN(
  106. SELECT DISTINCT department_id
  107. FROM departments
  108. WHERE location_id IN(1400,1700)
  109. );
  110. # 特殊变形
  111. SELECT last_name
  112. FROM employees
  113. WHERE department_id = ANY(
  114. SELECT DISTINCT department_id
  115. FROM departments
  116. WHERE location_id IN(1400,1700)
  117. );
  118. #等价于
  119. SELECT last_name
  120. FROM employees
  121. WHERE department_id IN(
  122. SELECT DISTINCT department_id
  123. FROM departments
  124. WHERE location_id IN(1400,1700)
  125. );
  126. #案例2:返回其它工种中比job_id为‘IT_PROG’工种任一工资低的员工的员工号、姓名、job_id 以及salary
  127. #①查询job_id为‘IT_PROG’部门任一工资
  128. SELECT DISTINCT salary
  129. FROM employees
  130. WHERE job_id = 'IT_PROG'
  131. #②查询员工号、姓名、job_id 以及salary,salary<(①)的任意一个
  132. SELECT last_name,employee_id,job_id,salary
  133. FROM employees
  134. WHERE salary<ANY(
  135. SELECT DISTINCT salary
  136. FROM employees
  137. WHERE job_id = 'IT_PROG'
  138. ) AND job_id<>'IT_PROG';
  139. #或
  140. SELECT last_name,employee_id,job_id,salary
  141. FROM employees
  142. WHERE salary<(
  143. SELECT MAX(salary)
  144. FROM employees
  145. WHERE job_id = 'IT_PROG'
  146. ) AND job_id<>'IT_PROG';
  147. #案例3:返回其它部门中比job_id为‘IT_PROG’部门所有工资都低的员工的员工号、姓名、job_id 以及salary
  148. SELECT last_name,employee_id,job_id,salary
  149. FROM employees
  150. WHERE salary<ALL(
  151. SELECT DISTINCT salary
  152. FROM employees
  153. WHERE job_id = 'IT_PROG'
  154. ) AND job_id<>'IT_PROG';
  155. #或
  156. SELECT last_name,employee_id,job_id,salary
  157. FROM employees
  158. WHERE salary<(
  159. SELECT MIN(salary)
  160. FROM employees
  161. WHERE job_id = 'IT_PROG'
  162. ) AND job_id<>'IT_PROG';
  163. #3、行子查询(结果集一行多列或多行多列)
  164. #案例:查询员工编号最小并且工资最高的员工信息
  165. SELECT *
  166. FROM employees
  167. WHERE (employee_id,salary)=(
  168. SELECT MIN(employee_id),MAX(salary)
  169. FROM employees
  170. );
  171. #①查询最小的员工编号
  172. SELECT MIN(employee_id)
  173. FROM employees
  174. #②查询最高工资
  175. SELECT MAX(salary)
  176. FROM employees
  177. #③查询员工信息
  178. SELECT *
  179. FROM employees
  180. WHERE employee_id=(
  181. SELECT MIN(employee_id)
  182. FROM employees
  183. )AND salary=(
  184. SELECT MAX(salary)
  185. FROM employees
  186. );
  187. #二、select后面
  188. /*
  189. 仅仅支持标量子查询
  190. */
  191. #案例:查询每个部门的员工个数
  192. SELECT d.*,(
  193. SELECT COUNT(*)
  194. FROM employees e
  195. WHERE e.department_id = d.department_id
  196. ) 员工个数
  197. FROM departments d;
  198. #案例2:查询员工号=102的部门名
  199. SELECT (
  200. SELECT department_name
  201. FROM departments d
  202. INNER JOIN employees e
  203. ON d.department_id=e.department_id
  204. WHERE e.employee_id=102
  205. ) 部门名;
  206. #三、from后面
  207. /*
  208. 将子查询结果充当一张表,要求必须起别名
  209. */
  210. #案例:查询每个部门的平均工资的工资等级
  211. #①查询每个部门的平均工资
  212. SELECT AVG(salary),department_id
  213. FROM employees
  214. GROUP BY department_id
  215. SELECT * FROM job_grades;
  216. #②连接①的结果集和job_grades表,筛选条件平均工资 between lowest_sal and highest_sal
  217. SELECT ag_dep.*,g.`grade_level`
  218. FROM (
  219. SELECT AVG(salary) ag,department_id
  220. FROM employees
  221. GROUP BY department_id
  222. ) ag_dep
  223. INNER JOIN job_grades g
  224. ON ag_dep.ag BETWEEN lowest_sal AND highest_sal;
  225. #四、exists后面(相关子查询)
  226. /*
  227. 语法:
  228. exists(完整的查询语句)
  229. 结果:
  230. 1或0
  231. */
  232. SELECT EXISTS(SELECT employee_id FROM employees WHERE salary=300000);
  233. #案例1:查询有员工的部门名
  234. #in
  235. SELECT department_name
  236. FROM departments d
  237. WHERE d.`department_id` IN(
  238. SELECT department_id
  239. FROM employees
  240. );
  241. #exists
  242. USE myemployees;
  243. SELECT department_name
  244. FROM departments d
  245. WHERE EXISTS(
  246. SELECT *
  247. FROM employees e
  248. WHERE d.`department_id`=e.`department_id`
  249. );
  250. #案例2:查询没有女朋友的男神信息
  251. #in
  252. USE girls;
  253. SELECT bo.*
  254. FROM boys bo
  255. WHERE bo.id NOT IN(
  256. SELECT boyfriend_id
  257. FROM beauty
  258. );
  259. #exists
  260. USE girls;
  261. SELECT bo.*
  262. FROM boys bo
  263. WHERE NOT EXISTS(
  264. SELECT boyfriend_id
  265. FROM beauty b
  266. WHERE bo.`id`=b.`boyfriend_id`
  267. );

进阶 8:分页查询

  1. 应用场景:
  2. 实际的web项目中需要根据用户的需求提交对应的分页查询的sql语句
  3. 语法:
  4. select 字段|表达式,...
  5. from
  6. where 条件】
  7. group by 分组字段】
  8. having 条件】
  9. order by 排序的字段】
  10. limit 【起始的条目索引,】条目数;
  11. 特点:
  12. 1.起始条目索引从0开始
  13. 2.limit子句放在查询语句的最后
  14. 3.公式:select * from limit page-1)*sizePerPage,sizePerPage
  15. 假如:
  16. 每页显示条目数sizePerPage
  17. 要显示的页数 page

查询语句案例:

  1. #案例1:查询前五条员工信息
  2. SELECT * FROM employees LIMIT 0,5;
  3. SELECT * FROM employees LIMIT 5;
  4. #案例2:查询第11条——第25条
  5. SELECT * FROM employees LIMIT 10,15;
  6. #案例3:有奖金的员工信息,并且工资较高的前10名显示出来
  7. SELECT *
  8. FROM employees
  9. WHERE commission_pct IS NOT NULL
  10. ORDER BY salary DESC
  11. LIMIT 10;

进阶 9:联合查询

  1. 引入:
  2. union 联合、合并:将多条查询语句的结果合并成一个结果
  3. 语法:
  4. select 字段|常量|表达式|函数 from 表】 where 条件】 union all
  5. select 字段|常量|表达式|函数 from 表】 where 条件】 union all
  6. select 字段|常量|表达式|函数 from 表】 where 条件】 union all
  7. .....
  8. select 字段|常量|表达式|函数 from 表】 where 条件】
  9. 应用场景:
  10. 要查询的结果来自于多个表,且多个表没有直接的连接关系,但查询的信息一致时
  11. 特点:
  12. 1、要求多条查询语句的查询列数是一致的!
  13. 2、要求多条查询语句的查询的每一列的类型和顺序最好一致
  14. 3union代表去重,union all代表不去重

代码实例

  1. #引入的案例:查询部门编号>90或邮箱包含a的员工信息
  2. SELECT * FROM employees WHERE email LIKE '%a%' OR department_id>90;
  3. SELECT * FROM employees WHERE email LIKE '%a%'
  4. UNION
  5. SELECT * FROM employees WHERE department_id>90;
  6. #案例:查询中国用户中男性的信息以及外国用户中年男性的用户信息
  7. SELECT id,cname FROM t_ca WHERE csex='男'
  8. UNION ALL
  9. SELECT t_id,tname FROM t_ua WHERE tGender='male';

查询总结

  1. 语法:
  2. select 查询列表
  3. from 1 别名
  4. 连接类型 join 2
  5. on 连接条件
  6. where 筛选
  7. group by 分组列表
  8. having 筛选
  9. order by排序列表
  10. limit 起始条目索引,条目数;

DML 语言

插入

  1. 语法:
  2. insert into 表名(字段名,...)
  3. values(值 1,...);
  4. 特点:
  5. 1、字段类型和值类型一致或兼容,而且一一对应
  6. 2、可以为空的字段,可以不用插入值,或用null填充
  7. 3、不可以为空的字段,必须插入值
  8. 4、字段个数和值的个数必须一致
  9. 5、字段可以省略,但默认所有字段,并且顺序和表中的存储顺序一致
  10. #一、插入语句
  11. #方式一:经典的插入
  12. /*
  13. 语法:
  14. insert into 表名(列名,...) values(值1,...);
  15. 说明:
  16. 1.插入的值的类型要与列的类型一致或兼容
  17. 2.不可以为null的列必须插入值。可以为null的列如何插入值?
  18. */
  19. USE girls;
  20. SELECT * FROM beauty;
  21. #1.插入的值的类型要与列的类型一致或兼容
  22. INSERT INTO beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
  23. VALUES(13,'唐艺昕','女','1990-4-23','1898888888',NULL,2);
  24. #2.不可以为null的列必须插入值。可以为null的列如何插入值?
  25. #方式一:
  26. INSERT INTO beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
  27. VALUES(13,'唐艺昕','女','1990-4-23','1898888888',NULL,2);
  28. #方式二:
  29. INSERT INTO beauty(id,NAME,sex,phone)
  30. VALUES(15,'娜扎','女','1388888888');
  31. #3.列的顺序是否可以调换
  32. INSERT INTO beauty(NAME,sex,id,phone)
  33. VALUES('蒋欣','女',16,'110');
  34. #4.列数和值的个数必须一致
  35. INSERT INTO beauty(NAME,sex,id,phone)
  36. VALUES('关晓彤','女',17,'110');
  37. #5.可以省略列名,默认所有列,而且列的顺序和表中列的顺序一致
  38. INSERT INTO beauty
  39. VALUES(18,'张飞','男',NULL,'119',NULL,NULL);
  40. #方式二:
  41. /*
  42. 语法:
  43. insert into 表名
  44. set 列名=值,列名=值,...
  45. */
  46. INSERT INTO beauty
  47. SET id=19,NAME='刘涛',phone='999';
  48. #两种方式大pk ★
  49. #1、方式一支持插入多行,方式二不支持
  50. INSERT INTO beauty
  51. VALUES(23,'唐艺昕1','女','1990-4-23','1898888888',NULL,2)
  52. ,(24,'唐艺昕2','女','1990-4-23','1898888888',NULL,2)
  53. ,(25,'唐艺昕3','女','1990-4-23','1898888888',NULL,2);
  54. #2、方式一支持子查询,方式二不支持
  55. INSERT INTO beauty(id,NAME,phone)
  56. SELECT 26,'宋茜','11809866';
  57. INSERT INTO beauty(id,NAME,phone)
  58. SELECT id,boyname,'1234567'
  59. FROM boys WHERE id<3;

修改

  1. #二、修改语句
  2. /*
  3. 1.修改单表的记录★
  4. 语法:
  5. update 表名
  6. set 列=新值,列=新值,...
  7. where 筛选条件;
  8. 2.修改多表的记录【补充】
  9. 语法:
  10. sql92语法:
  11. update 表1 别名,表2 别名
  12. set 列=值,...
  13. where 连接条件
  14. and 筛选条件;
  15. sql99语法:
  16. update 表1 别名
  17. inner|left|right join 表2 别名
  18. on 连接条件
  19. set 列=值,...
  20. where 筛选条件;
  21. */
  22. #1.修改单表的记录
  23. #案例1:修改beauty表中姓唐的女神的电话为13899888899
  24. UPDATE beauty
  25. SET phone = '13899888899'
  26. WHERE NAME LIKE '唐%';
  27. #案例2:修改boys表中id好为2的名称为张飞,魅力值 10
  28. UPDATE boys SET boyname='张飞',usercp=10
  29. WHERE id=2;
  30. #2.修改多表的记录
  31. #案例 1:修改张无忌的女朋友的手机号为114
  32. UPDATE boys bo
  33. INNER JOIN beauty b ON bo.`id`=b.`boyfriend_id`
  34. SET b.`phone`='114',bo.`userCP`=1000
  35. WHERE bo.`boyName`='张无忌';
  36. #案例2:修改没有男朋友的女神的男朋友编号都为2号
  37. UPDATE boys bo
  38. RIGHT JOIN beauty b ON bo.`id`=b.`boyfriend_id`
  39. SET b.`boyfriend_id`=2
  40. WHERE bo.`id` IS NULL;
  41. SELECT * FROM boys;

删除

  1. /*
  2. 方式一:delete
  3. 语法:
  4. 1、单表的删除【★】
  5. delete from 表名 where 筛选条件
  6. 2、多表的删除【补充】
  7. sql92语法:
  8. delete 表1的别名,表2的别名
  9. from 表1 表1的别名,表2 表2的别名
  10. where 连接条件
  11. and 筛选条件;
  12. sql99语法:
  13. delete 表1的别名,表2的别名
  14. from 表1 别名
  15. inner|left|right join 表2 别名 on 连接条件
  16. where 筛选条件;
  17. 方式二:truncate
  18. 语法:truncate table 表名;
  19. */
  20. #方式一:delete
  21. #1.单表的删除
  22. #案例:删除手机号以9结尾的女神信息
  23. DELETE FROM beauty WHERE phone LIKE '%9';
  24. SELECT * FROM beauty;
  25. #2.多表的删除
  26. #案例:删除张无忌的女朋友的信息
  27. DELETE b
  28. FROM beauty b
  29. INNER JOIN boys bo ON b.`boyfriend_id` = bo.`id`
  30. WHERE bo.`boyName`='张无忌';
  31. #案例:删除黄晓明的信息以及他女朋友的信息
  32. DELETE b,bo
  33. FROM beauty b
  34. INNER JOIN boys bo ON b.`boyfriend_id`=bo.`id`
  35. WHERE bo.`boyName`='黄晓明';
  36. #方式二:truncate语句(不可以添加筛选条件 表清空)
  37. #案例:将魅力值>100的男神信息删除
  38. TRUNCATE TABLE boys;

两种方式的区别【面试题】

  1. 1.delete 可以加 where 条件,truncate不能加
  2. 2.truncate删除,效率高一丢丢
  3. 3.假如要删除的表中有自增长列,
  4. 如果用delete删除后,再插入数据,自增长列的值从断点开始,
  5. truncate删除后,再插入数据,自增长列的值从1开始。
  6. 4.truncate删除没有返回值,delete删除有返回值
  7. 5.truncate删除不能回滚,delete删除可以回滚.

DDL 语句

库和表的管理

一、库的管理
创建、修改、删除
二、表的管理
创建、修改、删除
三、关键字
创建: create | 修改: alter | 删除: drop

库的管理:

  1. #1、库的创建
  2. /*
  3. 语法:
  4. create database [if not exists]库名;
  5. */
  6. #案例:创建库Books
  7. CREATE DATABASE IF NOT EXISTS books;
  8. #2、库的修改(已废弃)
  9. RENAME DATABASE books TO 新库名;
  10. #更改库的字符集
  11. ALTER DATABASE books CHARACTER SET gbk;
  12. #3、库的删除
  13. DROP DATABASE IF EXISTS books;

表的管理:

  1. #1.表的创建 ★
  2. /*
  3. 语法:
  4. create table 表名(
  5. 列名 列的类型【(长度) 约束】,
  6. 列名 列的类型【(长度) 约束】,
  7. 列名 列的类型【(长度) 约束】,
  8. ...
  9. 列名 列的类型【(长度) 约束】
  10. )
  11. */
  12. #案例:创建表Book
  13. USE books;
  14. CREATE TABLE book(
  15. id INT,#编号
  16. bName VARCHAR(20),#图书名
  17. price DOUBLE,#价格
  18. authorId INT,#作者编号
  19. publishDate DATETIME#出版日期
  20. );
  21. DESC book;
  22. #案例:创建表author
  23. CREATE TABLE IF NOT EXISTS author(
  24. id INT,
  25. au_name VARCHAR(20),
  26. nation VARCHAR(10)
  27. );
  28. DESC author;
  29. #2.表的修改
  30. /*
  31. 语法
  32. ALTER TABLE 表名 ADD|DROP|MODIFY|CHANGE COLUMN 列名 【列类型 约束】;
  33. */
  34. #①修改列名
  35. ALTER TABLE book CHANGE COLUMN publishdate pubDate DATETIME;
  36. #②修改列的类型或约束
  37. ALTER TABLE book MODIFY COLUMN pubdate TIMESTAMP;
  38. #③添加新列
  39. ALTER TABLE author ADD COLUMN annual DOUBLE;
  40. #④删除列
  41. ALTER TABLE author DROP COLUMN annual;
  42. #⑤修改表名
  43. ALTER TABLE author RENAME TO book_author;
  44. DESC book;
  45. DESC author;
  46. #3.表的删除
  47. DROP TABLE IF EXISTS book_author;
  48. SHOW TABLES;
  49. #通用的写法(操作流程):
  50. DROP DATABASE IF EXISTS 旧库名;
  51. CREATE DATABASE 新库名;
  52. SHOW DATABASES;
  53. DROP TABLE IF EXISTS 旧表名;
  54. CREATE TABLE 表名;
  55. SHOW TABLES;
  56. #4.表的复制
  57. INSERT INTO author VALUES
  58. (1,'村上春树','日本'),
  59. (2,'莫言','中国'),
  60. (3,'冯唐','中国'),
  61. (4,'金庸','中国');
  62. SELECT * FROM author;
  63. SELECT * FROM copy2;
  64. #1.仅仅复制表的结构
  65. CREATE TABLE copy LIKE author;
  66. #2.复制表的结构+数据
  67. CREATE TABLE copy2
  68. SELECT * FROM author;
  69. #3.只复制部分数据
  70. CREATE TABLE copy3
  71. SELECT id,au_name
  72. FROM author
  73. WHERE nation='中国';
  74. #4.仅仅复制某些字段
  75. CREATE TABLE copy4
  76. SELECT id,au_name
  77. FROM author
  78. WHERE 0;
  79. #这样复制有数据的
  80. CREATE TABLE copy4
  81. SELECT id,au_name
  82. FROM author
  83. # 删除废表
  84. DROP TABLE IF EXISTS copy5;

常见的数据类型

  1. 数值型:
  2. 整型
  3. 小数:
  4. 定点数
  5. 浮点数
  6. 字符型:
  7. 较短的文本:charvarchar
  8. 较长的文本:textblob(较长的二进制数据)
  9. 日期型:

整型:

  1. /*
  2. 分类:
  3. tinyint ---> 1个字节
  4. smallint ---> 2个字节
  5. mediumint ---> 3个字节
  6. int/integer ---> 4个字节
  7. bigint ---> 8个字节
  8. 特点:
  9. ① 如果不设置无符号还是有符号,默认是有符号,如果想设置无符号,需要添加unsigned关键字
  10. ② 如果插入的数值超出了整型的范围,会报out of range异常,并且插入临界值
  11. ③ 如果不设置长度,会有默认的长度
  12. 长度代表了显示的最大宽度,如果不够会用0在左边填充,但必须搭配zerofill使用!
  13. */
  14. #1.如何设置无符号和有符号
  15. CREATE DATABASE IF NOT EXISTS test;
  16. USE test;
  17. DROP TABLE IF EXISTS tab_int;
  18. CREATE TABLE tab_int(
  19. t1 INT,
  20. t2 INT UNSIGNED
  21. );
  22. # 7位 前边默认补零
  23. CREATE TABLE tab_int(
  24. t1 INT(7) ZEROFILL,
  25. t2 INT(7) ZEROFILL
  26. );
  27. DESC tab_int;
  28. INSERT INTO tab_int VALUES(-123456);
  29. INSERT INTO tab_int VALUES(-123456,-123456);
  30. INSERT INTO tab_int VALUES(2147483648,4294967296);
  31. INSERT INTO tab_int VALUES(123,123);
  32. SELECT * FROM tab_int;

小数型:

  1. /*
  2. 分类:
  3. 1.浮点型
  4. float(M,D)
  5. double(M,D)
  6. 2.定点型
  7. dec(M,D)
  8. decimal(M,D)
  9. 特点:
  10. M:整数部位+小数部位
  11. D:小数部位
  12. 如果超过范围,则插入临界值
  13. M和D都可以省略
  14. 如果是decimal,则M默认为10,D默认为0
  15. 如果是float和double,则会根据插入的数值的精度来决定精度
  16. ③定点型的精确度较高,如果要求插入数值的精度较高如货币运算等则考虑使用
  17. */
  18. #测试M和D
  19. USE test;
  20. CREATE DATABASE IF NOT EXISTS tab_float;
  21. DROP TABLE IF EXISTS tab_float;
  22. CREATE TABLE tab_float(
  23. f1 FLOAT,
  24. f2 DOUBLE,
  25. f3 DECIMAL
  26. );
  27. SELECT * FROM tab_float;
  28. DESC tab_float;
  29. INSERT INTO tab_float VALUES(123.4523,123.4523,123.4523);
  30. INSERT INTO tab_float VALUES(123.456,123.456,123.456);
  31. INSERT INTO tab_float VALUES(123.4,123.4,123.4);
  32. INSERT INTO tab_float VALUES(1523.4,1523.4,1523.4);
  33. #原则:
  34. /*
  35. 所选择的类型越简单越好,能保存数值的类型越小越好
  36. */

字符型:

  1. /*
  2. 较短的文本:
  3. char
  4. varchar
  5. 其他:
  6. binary和varbinary用于保存较短的二进制
  7. 类似于char和varchar,不同的是它们包含二进制字符串而不包含非二进制字符串
  8. enum用于保存枚举:要求插入的值必须属于列表中指定的值之一。不区分大小写
  9. 如果列表成员为1~255,则需要1个字节存储
  10. 如果列表成员为255~65535,则需要2个字节存储
  11. 最多需要65535个成员!
  12. set用于保存集合,不区分大小写
  13. 和Enum类型类似,里面可以保存0~64个成员。
  14. 和Enum类型最大的区别是: SET类型一次可以选取多个成员,而Enum只能选一个
  15. 根据成员个数不同,存储所占的字节也不同
  16. 成员数 字节数
  17. 1~8 1
  18. 9~16 2
  19. 17~24 3
  20. 25~32 4
  21. 33~64 8
  22. 较长的文本:
  23. text
  24. blob(较大的二进制)
  25. 特点:
  26. char:
  27. char(M) -- M表示最大的字符数,可以省略,默认为1,为0~255之间的整数; 固定长度的字符;比较耗费空间;但效率高
  28. varchar:
  29. varchar(M) -- M表示最大的字符数,不可以省略,为0~65535之间的整数;
  30. 可变长度的字符;比较节省空间;但效率低
  31. */
  32. CREATE TABLE tab_char(
  33. c1 ENUM('a','b','c')
  34. );
  35. INSERT INTO tab_char VALUES('a');
  36. INSERT INTO tab_char VALUES('b');
  37. INSERT INTO tab_char VALUES('c');
  38. INSERT INTO tab_char VALUES('m');
  39. INSERT INTO tab_char VALUES('A');
  40. SELECT * FROM tab_char;
  41. CREATE TABLE tab_set(
  42. s1 SET('a','b','c','d')
  43. );
  44. INSERT INTO tab_set VALUES('a');
  45. INSERT INTO tab_set VALUES('A,B');
  46. INSERT INTO tab_set VALUES('a,c,d');
  47. SELECT * FROM tab_set;
  48. DESC tab_set;

日期型:

  1. /*
  2. 分类:
  3. date 只保存日期
  4. time 只保存时间
  5. year 只保存年
  6. datetime 保存日期+时间
  7. timestamp 保存日期+时间
  8. 特点:
  9. 字节 范围 时区等的影响
  10. datetime 8 1000——9999 不受
  11. timestamp 4 1970-2038 受
  12. */
  13. CREATE TABLE tab_date(
  14. t1 DATETIME,
  15. t2 TIMESTAMP
  16. );
  17. INSERT INTO tab_date VALUES(NOW(),NOW());
  18. SELECT * FROM tab_date;
  19. SHOW VARIABLES LIKE 'time_zone';
  20. # 修改时区为东九区
  21. SET time_zone='+9:00';

常见约束

  1. NOT NULL
  2. DEFAULT
  3. UNIQUE
  4. CHECK
  5. PRIMARY KEY
  6. FOREIGN KEY

数据库事务

含义

通过一组逻辑操作单元(一组 DML——sql 语句),将数据从一种状态切换到另外一种状态

特点

(ACID)
原子性:要么都执行,要么都回滚
一致性:保证数据的状态操作前和操作后保持一致
隔离性:多个事务同时操作相同数据库的同一个数据时,一个事务的执行不受另外一个事务的干扰
持久性:一个事务一旦提交,则数据将持久化到本地,除非其他事务对其进行修改

相关步骤:

  1. 1、开启事务
  2. 2、编写事务的一组逻辑操作单元(多条sql语句)
  3. 3、提交事务或回滚事务

事务的分类:

隐式事务,没有明显的开启和结束事务的标志

  1. 比如
  2. insertupdatedelete语句本身就是一个事务

显式事务,具有明显的开启和结束事务的标志

  1. 1、开启事务
  2. 取消自动提交事务的功能
  3. 2、编写事务的一组逻辑操作单元(多条sql语句)
  4. insert
  5. update
  6. delete
  7. 3、提交事务或回滚事务

使用到的关键字

  1. set autocommit=0;
  2. start transaction;
  3. commit;
  4. rollback;
  5. savepoint 断点
  6. commit to 断点
  7. rollback to 断点

事务的隔离级别:

事务并发问题如何发生?

  1. 当多个事务同时操作同一个数据库的相同数据时

事务的并发问题有哪些?

  1. 脏读:一个事务读取到了另外一个事务未提交的数据
  2. 不可重复读:同一个事务中,多次读取到的数据不一致
  3. 幻读:一个事务读取数据时,另外一个事务进行更新,导致第一个事务读取到了没有更新的数据

如何避免事务的并发问题?

  1. 通过设置事务的隔离级别
  2. 1READ UNCOMMITTED
  3. 2READ COMMITTED 可以避免脏读
  4. 3REPEATABLE READ 可以避免脏读、不可重复读和一部分幻读
  5. 4SERIALIZABLE可以避免脏读、不可重复读和幻读

设置隔离级别:

  1. set session|global transaction isolation level 隔离级别名;

查看隔离级别:

  1. select @@tx_isolation;

视图

含义:理解成一张虚拟的表

视图和表的区别:

  1. 使用方式 占用物理空间
  2. 视图 完全相同 不占用,仅仅保存的是sql逻辑
  3. 完全相同 占用

视图的好处:

  1. 1sql语句提高重用性,效率高
  2. 2、和表实现了分离,提高了安全性

视图的创建

语法:
CREATE VIEW 视图名
AS
查询语句; ###视图的增删改查
1、查看视图的数据 ★

  1. SELECT * FROM my_v4;
  2. SELECT * FROM my_v1 WHERE last_name='Partners';
  3. 2、插入视图的数据
  4. INSERT INTO my_v4(last_name,department_id) VALUES('虚竹',90);
  5. 3、修改视图的数据
  6. UPDATE my_v4 SET last_name ='梦姑' WHERE last_name='虚竹';

4、删除视图的数据
DELETE FROM my_v4; ###某些视图不能更新
包含以下关键字的 sql 语句:分组函数、distinct、group by、having、union 或者 union all
常量视图
Select 中包含子查询
join
from 一个不能更新的视图
where 子句的子查询引用了 from 子句中的表 ###视图逻辑的更新 #方式一:
CREATE OR REPLACE VIEW test_v7
AS
SELECT last_name FROM employees
WHERE employee_id>100;

  1. #方式二:
  2. ALTER VIEW test_v7
  3. AS
  4. SELECT employee_id FROM employees;
  5. SELECT * FROM test_v7;

视图的删除

DROP VIEW test_v1,test_v2,test_v3; ###视图结构的查看
DESC test_v7;
SHOW CREATE VIEW test_v7;

存储过程

含义:一组经过预先编译的 sql 语句的集合
好处:

  1. 1、提高了sql语句的重用性,减少了开发程序员的压力
  2. 2、提高了效率
  3. 3、减少了传输次数

分类:

  1. 1、无返回无参
  2. 2、仅仅带in类型,无返回有参
  3. 3、仅仅带out类型,有返回无参
  4. 4、既带in又带out,有返回有参
  5. 5、带inout,有返回有参
  6. 注意:inoutinout都可以在一个存储过程中带多个

创建存储过程

语法:

  1. create procedure 存储过程名(in|out|inout 参数名 参数类型,...)
  2. begin
  3. 存储过程体
  4. end

类似于方法:

  1. 修饰符 返回类型 方法名(参数类型 参数名,...){
  2. 方法体;
  3. }

注意

  1. 1、需要设置新的结束标记
  2. delimiter 新的结束标记
  3. 示例:
  4. delimiter $
  5. CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,...)
  6. BEGIN
  7. sql语句1;
  8. sql语句2;
  9. END $
  10. 2、存储过程体中可以有多条sql语句,如果仅仅一条sql语句,则可以省略begin end
  11. 3、参数前面的符号的意思
  12. in:该参数只能作为输入 (该参数不能做返回值)
  13. out:该参数只能作为输出(该参数只能做返回值)
  14. inout:既能做输入又能做输出

调用存储过程

call 存储过程名(实参列表) ##函数

创建函数

学过的函数:LENGTH、SUBSTR、CONCAT 等
语法:

  1. CREATE FUNCTION 函数名(参数名 参数类型,...) RETURNS 返回类型
  2. BEGIN
  3. 函数体
  4. END

调用函数

SELECT 函数名(实参列表)

函数和存储过程的区别

  1. 关键字 调用语法 返回值 应用场景
  2. 函数 FUNCTION SELECT 函数() 只能是一个 一般用于查询结果为一个值并返回时,当有返回值而且仅仅一个
  3. 存储过程 PROCEDURE CALL 存储过程() 可以有0个或多个 一般用于更新

流程控制结构

系统变量

一、全局变量

作用域:针对于所有会话(连接)有效,但不能跨重启

  1. 查看所有全局变量
  2. SHOW GLOBAL VARIABLES;
  3. 查看满足条件的部分系统变量
  4. SHOW GLOBAL VARIABLES LIKE '%char%';
  5. 查看指定的系统变量的值
  6. SELECT @@global.autocommit;
  7. 为某个系统变量赋值
  8. SET @@global.autocommit=0;
  9. SET GLOBAL autocommit=0;

二、会话变量

作用域:针对于当前会话(连接)有效

  1. 查看所有会话变量
  2. SHOW SESSION VARIABLES;
  3. 查看满足条件的部分会话变量
  4. SHOW SESSION VARIABLES LIKE '%char%';
  5. 查看指定的会话变量的值
  6. SELECT @@autocommit;
  7. SELECT @@session.tx_isolation;
  8. 为某个会话变量赋值
  9. SET @@session.tx_isolation='read-uncommitted';
  10. SET SESSION tx_isolation='read-committed';

自定义变量

一、用户变量

声明并初始化:

  1. SET @变量名=值;
  2. SET @变量名:=值;
  3. SELECT @变量名:=值;

赋值:

  1. 方式一:一般用于赋简单的值
  2. SET 变量名=值;
  3. SET 变量名:=值;
  4. SELECT 变量名:=值;
  5. 方式二:一般用于赋表 中的字段值
  6. SELECT 字段名或表达式 INTO 变量
  7. FROM 表;

使用:

  1. select @变量名;

二、局部变量

声明:

  1. declare 变量名 类型 default 值】;

赋值:

  1. 方式一:一般用于赋简单的值
  2. SET 变量名=值;
  3. SET 变量名:=值;
  4. SELECT 变量名:=值;
  5. 方式二:一般用于赋表 中的字段值
  6. SELECT 字段名或表达式 INTO 变量
  7. FROM 表;

使用:

  1. select 变量名

二者的区别:

  1. 作用域 定义位置 语法

用户变量 当前会话 会话的任何地方 加@符号,不用指定类型
局部变量 定义它的 BEGIN END 中 BEGIN END 的第一句话 一般不用加@,需要指定类型

分支

一、if 函数
语法:if(条件,值 1,值 2)
特点:可以用在任何位置

二、case 语句

语法:

  1. 情况一:类似于switch
  2. case 表达式
  3. when 1 then 结果1或语句1(如果是语句,需要加分号)
  4. when 2 then 结果2或语句2(如果是语句,需要加分号)
  5. ...
  6. else 结果n或语句n(如果是语句,需要加分号)
  7. end case】(如果是放在begin end中需要加上case,如果放在select后面不需要)
  8. 情况二:类似于多重if
  9. case
  10. when 条件1 then 结果1或语句1(如果是语句,需要加分号)
  11. when 条件2 then 结果2或语句2(如果是语句,需要加分号)
  12. ...
  13. else 结果n或语句n(如果是语句,需要加分号)
  14. end case】(如果是放在begin end中需要加上case,如果放在select后面不需要)

特点:
可以用在任何位置

三、if elseif 语句

语法:

  1. if 情况1 then 语句1;
  2. elseif 情况2 then 语句2;
  3. ...
  4. else 语句n;
  5. end if;

特点:
只能用在 begin end 中!!!!!!!!!!!!!!!

三者比较:
应用场合
if 函数 简单双分支
case 结构 等值判断 的多分支
if 结构 区间判断 的多分支

循环

语法:

  1. 【标签:】WHILE 循环条件 DO
  2. 循环体
  3. END WHILE 【标签】;

特点:

  1. 只能放在BEGIN END里面
  2. 如果要搭配leave跳转语句,需要使用标签,否则可以不用标签
  3. leave类似于java中的break语句,跳出所在循环!!!