MySQL

时间:2021-03-08 13:37:24   收藏:0   阅读:0

MySQL

一,为什么要学习数据库

数据库的好处

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

二,数据库相关的概念

DBMS

DB

SQL

SQL的优点

  1. 不是某个特定的数据库供应商专有的语言,几乎所有的DBMS都支持SQL
  2. 简单易学
  3. 虽然简单,但是实际上是一种强有力的语言,灵活使用其语言元素,可以进行非常复杂和高级的数据库操作。

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

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

四, 初始mysql

MySQL产品的介绍

优点:

DBMS分为两类

MySQL的目录结构

  1. bin目录:用于放置一些可执行的文件。
  2. data目录:用于放置一些日志文件以及数据库。
  3. include目录:用于放置一些头文件。
  4. ilb目录:用于放置一系列的库文件。
  5. share目录:用于存放字符集语言等信息。
  6. my.ini:是MySQL数据库中使用的配置文件。
  7. my-huge.ini:适合超大型数据库的配置文件。
  8. my-large.ini:适合大型数据库的配置文件。
  9. my-medium.ini:适合中小型数据库的配置文件。
  10. my-small.ini:适合小型数据库的配置文件。
  11. my-template.ini:是配置文件的模板,MySQL配置向导将配置文件中选择项写入到my.ini文件中。
  12. my-innodb-heavy-4G.ini:表示配置文件只对于InnoDB存储引擎有效,而且服务器的内存不能小于4G。

MySQL产品的安装

MySQL服务的启动和停止

  1. 通过命令行
    • net start mysql
    • net stop mysql
  2. 方式二:计算机 -- 右击 -- 管理 -- 服务

MySQL服务的登陆和退出

MySQL常见的命令

查看数据库的版本

  1. 在myslq客户端:select version();
  2. 在Windows命令提示符中输入:mysql --version

显示都有那些数据库:show databases ;

使用某个数据库:use 指定的库名;

查看表:show tables; / show tables from 库名称;

查看当前在那个库:select database();

创建表:create table 表名 (id int, name varchar(20));

查看表结构:desc 表名; describe的缩写

查看数据库的编码字符集:show create database 数据库名称;

查看表所有的列:show full columns from 表名;

查看表数据:select * from 表名;

插入行数据:insert into 表名 (列名1,列名2,...) value(值1,值2,...);

修改列操作:update 表名 set 列名=‘值‘ where id = ? ;

删除列:delete from 表名 where id=?;

MySQL的语法规范

  1. 不区分大小写,但建议关键字大写,表名,列名小写

  2. 每条命令最好用分号结尾

  3. 每条命令根据需要,可以进行缩进 或者换行

  4. 注释

    单行注释:#注释文字

    单行注释:-- 注释文字

    多行注释:/* 注释文字 */

五, DQL语言的学习(Data Query Language)

基础查询

1. 查询表中的单个字段

SELECT last_name FROM employees;

2. 查询表中的多个字段

SELECT last_name,salary,email FROM employees;

3. 查询表中的所有字段

SELECT 
  employee_id,
  first_name,
  last_name,
  email,
  phone_number,
  job_id,
  salary,
  commission_pct,
  manager_id,
  department_id,
  hiredate 
FROM
  employees ;
# * 代表所有字段
SELECT * FROM employees;

4. 查询常量值

SELECT 100; #100
SELECT ‘john‘;#john 

5. 查询表达式

SELECT 100%98; #2

6. 查绚函数

#version() 查看MySQL的版本号
SELECT VERSION();

7. 起别名

注意事项:

  1. 便于理解。
  2. 如果要查询的字段有重名的情况,使用起别名可以区分开来
  3. 如果别名有特殊符号:空格,#号,等等。建议把别名加上双引号/单引号

格式:

# 方式一:使用 as
SELECT 100%98 AS 结果;
SELECT last_name AS 姓,first_name AS 名 FROM employees;
# 方式二:使用空格
SELECT last_name 姓,first_name 名 FROM employees;
#案例:查询salary,显示结果位 out put
SELECT	salary AS ‘out put‘ FROM employees;

8. 去重:

#案例:查询员工表中涉及到的所有的部门编号
SELECT DISTINCT department_id FROM employees ;

9. +号的作用:

作用(回忆):

  1. 运算符,两个操作数都为数值型
  2. 连接符,只要有一个操作数为字符串
MySQL中的+号
仅仅只有一个功能:运算符
select  100+90; 两个操作数都为数值型,则做加法运算
select ‘123‘+90;只要其中一方为字符型,试图将字符型数值转换成数值型。
					如果转换成功,则继续做加法运算
select ‘john‘+90;	如果转换失败,则将字符型值转换成0

select null+10;只要其中一方为null,则结果肯定为null

10. 使用concat函数实现连接

#select last_name+first_name as 姓名 from employees; #错误?的
SELECT  CONCAT(last_name,first_name ) AS 姓名 FROM employees;

11. ifnull函数

select ifnull (commission_pct,0) from employees;

12.isnull函数

SELECT ISNULL(commission_pct),commission_pct FROM employees;

条件查询

一,按条件运算符筛选

二,按逻辑表达式筛选

三,模糊查询

1. like
2. between and
3. in
4. is null / is not null
5.安全等于:<=>

排序查询

案例:

  1. 案例1:查询员工信息,要求工资从高到底排序

    SELECT * FROM employees ORDER BY salary DESC;
    
  2. 案例2:查询部门编号>=90的员工信息,按入职时间的先后进行排序【添加筛选条件】

    SELECT * FROM employees
    WHERE department_id >=90
    ORDER BY hiredate ASC;
    
  3. 案例3:按年薪的高低显示员工的信息和年薪【按表达式排序】

    SELECT *,salary*12*(1+IFNULL(commission_pct,0)) ‘年薪‘ FROM employees 
    ORDER BY salary*12*(1+IFNULL(commission_pct,0)) DESC;
    
  4. 案例4:按年薪的高低显示员工的信息和年薪【按别名排序】

    SELECT *,salary*12*(1+IFNULL(commission_pct,0)) 年薪 FROM employees 
    ORDER BY 年薪 DESC;
    
  5. 案例5:按姓名的长度显示员工的姓名和工资【按函数排序】

    SELECT LENGTH(last_name) 字节长度,last_name,salary
    FROM employees ORDER BY LENGTH(last_name) DESC;
    
  6. 案例6:查询员工信息,要求先按工资升序,再按员工编号降序【按多个字段排序】

    SELECT * FROM employees
    ORDER BY salary ASC ,employee_id DESC;
    

常见的函数

类似于Java的方法,将一组逻辑语句封装在方法中,对外暴露方法名

一,字符函数

  1. length 获取参数值的字节个数

    SELECT LENGTH(‘john‘);#4
    SELECT LENGTH(‘呵呵呵‘);#9 (utf-8中文占3个字节)
    # 查看客户端使用的字符集
    SHOW VARIABLES LIKE ‘%char%‘;
    
  2. concat 拼接字符串

    SELECT CONCAT(last_name,‘_‘,first_name) 姓名 FROM employees;
    
  3. upper,lower 变大写边小写

    SELECT UPPER(‘jhon‘);#JHON
    SELECT LOWER(‘jHon‘);#jhon
    #实例:将姓变大写,名变小写,然后拼接
    SELECT CONCAT(UPPER( last_name),LOWER (first_name)) 姓名 FROM employees;
    
  4. substr,substring

    注意:索引从1开始

    #截取从指定索引处后面所有字符
    SELECT SUBSTR(‘李莫愁爱上了陆展元‘,7); out_put;#陆展元
    
    #截取从指定索引处指定字符长度的字符
    SELECT SUBSTR(‘李莫愁爱上了陆展元‘,1,3); out_put;#李莫愁
    
    #案例:姓名中首字符大写,其他字符小写然后用_拼接,显示出来
    SELECT CONCAT( UPPER( SUBSTR(last_name,1,1)),‘_‘,LOWER(SUBSTR(last_name,2)) )
    FROM employees;
    
  5. **instr **返回子串第一次出现的索引,如果找不到返回0

    SELECT INSTR(‘杨不悔爱上了殷六侠‘,‘殷六侠‘) AS out_put;#7
    
  6. **trim **前后去重

    SELECT LENGTH(TRIM(‘   张翠山   ‘)) out_put;#9
    SELECT TRIM(‘a‘ FROM ‘aaaaaaa张aa翠aa山aaaaa‘) out_put ;#张aa翠aa山
    
  7. lpad 使用指定的字符实现左填充指定长度

    SELECT LPAD(‘殷素素‘,10,"*") AS out_put;#*******殷素素
    SELECT LPAD(‘殷素素‘,2,"*") AS out_put;#殷素
    
  8. **rpad **使用指定的字符实现右填充指定长度

    SELECT RPAD(‘殷素素‘,12,"ab") AS out_put;#殷素素ababababa
    SELECT RPAD(‘殷素素‘,2,"ab") AS out_put;#殷素
    
  9. replace 替换

    SELECT REPLACE(‘张无忌爱上了周驰若‘,‘周驰若‘,‘赵敏‘) out_put;#张无忌爱上了赵敏
    SELECT REPLACE(‘周驰若爱上了周驰若‘,‘周驰若‘,‘赵敏‘) out_put;#赵敏爱上了赵敏
    

二,数学函数

  1. **round **四舍五入

    SELECT ROUND(2.5);#3
    SELECT ROUND(-1.4);#-1
    SELECT ROUND(-1.5);#-2
    SELECT ROUND(1.5767,2);#1.58  
    
  2. ceil 向上取整,返回>=该参数的最小整数

    SELECT CEIL(1.0001);#2
    SELECT CEIL(-1.02);#-1
    
  3. **floor **向下取整,返回<=该参数的最大整数

    SELECT FLOOR(9.99);#9
    SELECT FLOOR(-9.99);#10  
    
  4. **truncate **截断

    SELECT TRUNCATE(1.6999,1);#1,6   
    
  5. **mod **取余

    mod(a,b) : a-a/b*b

    mod(10,-3) : -10-(-10)/(-3)*(-3)=-1

    SELECT MOD(10,3);#1
    SELECT MOD(-10,3);#-1
    
  6. rand:获取随机数,返回0-1之间的小数

三.1,日期函数

  1. now 返回当前系统日期+时间

    SELECT NOW();
    
  2. curdate 返回当前系统日期,不包含时间

    SELECT CURDATE();
    
  3. curtime 返回当前时间,不包含日期

    SELECT CURTIME();
    
  4. 可以获取指定的部分,年,月,日,小时,分钟,秒

    SELECT YEAR(NOW()) 年;
    SELECT YEAR(‘2020-12-1‘) 年;
    #查询入职时间
    SELECT YEAR (hiredate) FROM employees;
    
    #查询月份中文
    SELECT MONTH(NOW()) 月;
    #查询月份英文
    SELECT MONTHNAME(NOW()) 月;
    #日day,小时hour,分钟minute ,秒second 
    
  5. datediff两个日期之差

    SELECT DATEDIFF(NOW(),‘2000-11-08‘);	
    SELECT DATEDIFF(‘2020-1-3‘,‘2020-1-10‘);#-7 
    

三.2,字符日期转换函数

四,其他函数

SELECT VERSION();#查看当前MySQL的版本
SELECT DATABASE();# 查看当前数据库
SELECT USER();# 查看当前用户
select md5(‘字符‘)#返回该字符的md5的密码形式
select password(‘字符‘);#返回该字符的密码形式

五,流程控制函数

  1. if函数 ??*if else **的效果

    格式:if(条件表达式,表达式成立返回的值,条件表达式不成立返回的值)

    SELECT IF(10>5,‘大‘,‘小‘);#大
    SELECT last_name,commission_pct,IF(commission_pct IS NOT NULL,‘有奖金‘,‘没奖金‘) FROM employees ;
    
  2. case函数的使用一:switch case 的效果

    • java中:

      switch(变量或表达式){
      	case 常量1:语句1;break;
      	...
      	default:语句n;break;
      }
      
    • MySQL中:

      case 要判断的字段或表达式
      when 常量1 then 要显示的值1或语句1;
      when 常量2 then 要显示的值1或语句2;
      ...
      else 要显示的值n或语句n;
      end
      
    • 案例:查询员工的工资,要求
      部门号=30,显示的工资为1.1倍
      部门号=40,显示的工资为1.2倍
      部门号=50,显示的工资为1.3倍
      其他部门,显示的工资为原工资

      SELECT department_id,salary 原始工资,
      CASE department_id
      WHEN 30 THEN salary*1.1
      WHEN 40 THEN salary*1.2
      WHEN 50 THEN salary*1.3
      ELSE salary 
      END 新工资 FROM employees
      ORDER  BY department_id;
      
  3. case函数的使用二:类似于 多种if

    • java中:

      if(条件1){
      	语句1;
      }else if(条件2){
      	语句2;
      }
      ...
      else{
       	语句n;
      }
      
    • MySQL中:

      case 
      when 条件1 then 要显示的值1或语句1
      when 条件2 then 要显示的值2或语句2
      ...
      else 要显示的值n或语句n
      end
      
    • 案例:查询员工的工资的情况
      如果工资>20000,显示A级别
      如果工资>15000,显示B级别
      如果工资>10000,显示C级别
      否则,显示D级别

      SELECT employee_id,salary,
      CASE 
      WHEN salary>20000 THEN ‘A‘
      WHEN salary>15000 THEN ‘B‘
      WHEN salary>10000 THEN ‘C‘
      ELSE ‘D‘
      END 级别 FROM employees
      ORDER BY salary DESC;
      

分组函数

  1. 简单的使用

    SELECT SUM(salary) FROM employees;
    SELECT AVG(salary) FROM employees;
    SELECT MAX(salary) FROM employees;
    SELECT MIN(salary) FROM employees;
    SELECT COUNT(salary) FROM employees;
    
    SELECT SUM(salary) 和,AVG(salary) 平均,MAX(salary) 最大,MIN(salary) 最小,COUNT(salary) 个数 
    FROM employees;
    SELECT SUM(salary) 和,ROUND(AVG(salary),2)平均,MAX(salary) 最大,MIN(salary) 最小,COUNT(salary) 个数 
    FROM employees;#平均值保留两位小数
    
  2. 参数支持那些类型

    SELECT SUM(last_name),AVG(last_name) FROM employees;#不支持
    SELECT SUM(hiredate), AVG(hiredate) FROM employees;#不支持
    # sum avg 一般用于处理数值型 
    
    SELECT MAX(last_name),MIN(last_name) FROM employees;
    SELECT MAX(hiredate),MIN(hiredate) FROM employees;
    # max min 支持字符和日期型
    
    SELECT COUNT(commission_pct) FROM employees; 
    SELECT COUNT(last_name) FROM employees;
    # count 只支持不为null的值  
    
  3. 是否忽略null

    SELECT SUM(commission_pct),AVG(commission_pct),SUM(commission_pct)/35,SUM(commission_pct)/107 FROM employees;
    SELECT MAX(commission_pct),MIN(commission_pct) FROM employees;
    SELECT COUNT(commission_pct) FROM employees;
    SELECT commission_pct FROM employees; 
    
  4. distinct搭配

    SELECT SUM(DISTINCT salary),SUM(salary) FROM employees;
    SELECT COUNT(DISTINCT salary),COUNT(salary) FROM employees;  
    
  5. **count **函数的详细介绍

    SELECT COUNT(salary) FROM employees;
    SELECT COUNT(*)FROM employees;#统计行数
    SELECT COUNT(1)FROM employees;#统计行数
    效率:
    MYISAM 存储引擎下,COUNT(*) 的效率高
    INNODB 存储引擎下,COUNT(*)和COUNT(1)的效率差不多,比COUNT(字段)要高一些
    
  6. 和分组函数数一同查询的字段有限制

    SELECT AVG(salary),employee_idl FROM employees;#意义不大
    

分组查询

引入

#查询每个部门的平均工资
SELECT department_id,AVG(salary) FROM employees 
GROUP BY department_id ORDER BY department_id;

#案例1,查询每个工种的最高工资
SELECT MAX(salary),job_id 
FROM employees GROUP BY job_id;

#案例2,查询每个位置的部门的个数
SELECT COUNT(*),location_id FROM departments GROUP BY location_id;

添加分组前的筛选条件

#案例1:查询邮箱中包含a字符的,每个部门的平均工资
SELECT AVG(salary),department_id FROM employees 
WHERE email LIKE ‘%a%‘ 
GROUP BY department_id;

#案例2:查询有奖金的每个领导手下员工的最高工资
SELECT MAX(salary),manager_id
FROM employees 
WHERE commission_pct IS NOT NULL
GROUP BY employee_id;

添加分组后的筛选条件

#1. 查询每个部门的员工个数
SELECT COUNT(*) a,department_id
FROM employees
GROUP BY department_id;
#2. 根据1的结果进行筛选,查询那个部门的员工个数>2
SELECT COUNT(*) a,department_id
FROM employees
GROUP BY department_id
HAVING a>2;

#案例2:查询每个工种有奖金的员工的做高工资>12000的工种编号和最高工资
#1. 查询每个工种有奖金的员工的最高工资
#2. 根据1结果继续筛选,最高工资>12000
SELECT job_id,MAX(salary) a
FROM employees
WHERE commission_pct IS NOT NULL 
GROUP BY job_id
HAVING a>12000;

#案例3:查询领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个,以及其最低工资
#1. 查询每个领导手下的员工固定最低工资
#2. 添加筛选条件:编号>102
#3. 添加筛选条件:最低工资>5000
SELECT MIN(salary) a,manager_id 
FROM employees
WHERE manager_id>102
GROUP BY manager_id
HAVING a>5000;

按表达式或函数分组

#案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些
#1. 查询每个长度的员工个数
#2. 添加筛选条件
SELECT  COUNT(*) a,LENGTH(last_name) b
FROM employees
GROUP BY b
HAVING a>5;

按多个字段分组

#案例:查询每个部门每个工种的员工的平均工资
SELECT AVG(salary),department_id,job_id
FROM employees
GROUP BY department_id,job_id;

添加排序

#案例:查询每个部门每个工种的员工的平均工资,并且按平均工资的高低显示
SELECT AVG(salary) a,department_id,job_id
FROM employees
GROUP BY department_id,job_id
HAVING a>10000
ORDER BY a DESC;

练习

USE myemployees;
#1. 查询各job_id的员工工资的最大值,最小值,平均值,总和,并按job_id升序
SELECT job_id,MAX(salary),MIN(salary),ROUND( AVG(salary),2),SUM(salary)
FROM employees 
GROUP BY job_id 
ORDER BY job_id ASC;
#2. 查询员工最高工资和最低工资的差距
SELECT MAX(salary)-MIN(salary)
FROM employees ;
#3. 查询各个管理者手下员工的最低工资,其中最低工资不能小于6000,没有管理者的员工不计算在内
SELECT MIN(salary) s
FROM employees
WHERE manager_id IS NOT NULL
GROUP BY manager_id
HAVING s>=6000;
#4. 查询所有部门的编号,员工数量和工资平均值,并按平均工资降序
SELECT department_id,COUNT(*),AVG(salary) a
FROM employees
GROUP BY department_id
ORDER BY  a DESC;
#5. 选择具有各个job_id的员工人数
SELECT COUNT(*),job_id FROM employees GROUP BY job_id;

连接查询

一,含义

二,分类

按年代分类

按功能分类

三,sql92语法

  1. 等值连接

    • 语法:

      select 查询列表
      from 表2 别名,表2 别名
      where 表1.key=表2.key
      【and 筛选条件】
      【group by 分组字段】
      【having 分组后的筛选】
      【order by 排序字段】
      
    • 特点:

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

    • 语法:

      select 查询列表
      from 表2 别名,表2 别名
      where 表1.key=表2.key
      【and 筛选条件】
      【group by 分组字段】
      【having 分组后的筛选】
      【order by 排序字段】
      
  3. 自连接

    • 语法:

      select 查询列表
      from 表2 别名,表2 别名
      where 表1.key=表2.key
      【and 筛选条件】
      【group by 分组字段】
      【having 分组后的筛选】
      【order by 排序字段】
      

四,sql99语法

语法:

	select 查询列表
	from 表1 别名 
	【连接类型】
	join 表2 别名
	on 连接条件
	【where 筛选条件】
	【group by 分组】
	【having 筛选条件】
	【order by 排序列表】

分类:

特点,语法:

  1. 内连接

    语法:

    select 查询列表
    from 表1 别名
    inner join 表2 别名
    on 连接条件
    

    分类:等值,非等值,自连接

    特点:

    1. 添加排序,分组,筛选
    2. **inner **可以省略
    3. 筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
    4. inner join连接和sql92语法中的等值连接效果是一样的,都是查询多表的交集
    5. 表的顺序可以调换
  2. 外连接

    语法:

    select 查询列表
    from 表1 别名
    left|right|full outer join 表2 别名
    on 连接条件
    

    应用场景:用于查询一个表中有,另一个表没有的记录

    特点:

    1. 外连接的查询结果为主表中的所有记录
      如果从表中有和它匹配的,则显示匹配的值
      如果从表中没有和它匹配的,则显示null
      外连接查询结果=内连接查询结果+主表中有而从表没有的记录
    2. 左外连接,left join 左边的是主表
      右外连接,
      right join
      右边的是主表
    3. 左外和右外交换两个表的顺序,可以实现同样的效果
    4. 全外连接=内连接的结果+表1中有但表2没有的+表2中有但表1没有的
    5. outer可以省略
  3. 交叉连接

    语法:

    select 查询列表
    from 表1 别名
    cross join 表2 别名
    

    特点:使用99语法实现笛卡尔乘积

sql99 和 sql99区别:

代码实例:

USE girls;
SELECT	* FROM beauty;
SELECT * FROM boys;
SELECT NAME,boyName FROM boys,beauty;#这种现象称之为笛卡尔积现象

SELECT NAME,boyName FROM boys,beauty
WHERE boys.id=beauty.boyfriend_id;#连接条件

sql92标准

  1. 等值连接

    1. 简单的等值连接

      #案例1:查询女神名对应的男神名
       SELECT *,boys.`boyName`
       FROM beauty,boys
       WHERE beauty.boyfriend_id=boys.id;
       #案例2:查询员工名对应的部门名
       USE myemployees;
       SELECT last_name,department_name
       FROM employees,departments
       WHERE employees.`department_id`=departments.`department_id`;
      
    2. 为表起别名

      • 提高语句的简洁度

      • 区分多个重名的字段

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

      #查询员工名,工种号,工种名
      SELECT last_name,e.job_id,job_title
      FROM employees e,jobs j
      WHERE e.job_id=j.job_id;
      
    3. 两个表的顺序是否可以调换

      #查询员工名,工种号,工种名
      SELECT last_name,e.job_id,job_title
      FROM jobs j,employees e
      WHERE j.job_id= e.job_id;
      
    4. 可以加筛选

      #案例:查询有奖金的员工名,部门名
      SELECT last_name,department_name
      FROM employees e,departments d
      WHERE e.`department_id`=d.`department_id` AND commission_pct IS NOT NULL;
      #案例2:查询城市中第二个字符为o的部门名和城市名
      SELECT department_name,city	
      FROM departments d,locations l
      WHERE d.`location_id`=l.`location_id` AND l.`city` LIKE ‘_o%‘;
      
    5. 可以加分组

      #案例1:查询每个城市的部门个数
      SELECT COUNT(*),city
      FROM  departments d,locations l
      WHERE d.`location_id`=l.`location_id`
      GROUP BY city;
      #案例2:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资
      SELECT department_name,d.`manager_id`,MIN(salary)
      FROM employees e,departments d
      WHERE e.`department_id`=d.`department_id` AND commission_pct IS NOT NULL 
      GROUP BY e.`department_id`;
      
    6. 可以加排序

      #案例:查询每个工种的工种名和员工的个数,并且按员工个数降序
      SELECT job_title,COUNT(*) a  
      FROM employees e,jobs j
      WHERE e.`job_id`=j.`job_id` 
      GROUP BY e.`job_id`
      ORDER BY a DESC;
      
    7. 可以实现三表连接

      #案例:查询员工名,部门名和所在的城市
      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`;
      
  2. 非等值连接

    #案例1:查询员工的工资和工资级别
    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 * FROM job_grades;
    
  3. 自连接

    #案例:查询员工名和上级的名称
    SELECT a.`last_name` 领导,b.`last_name` 员工
    FROM employees a,employees b
    WHERE a.`employee_id`=b.`manager_id`;
    

sql99

  1. 内连接

    • 等值连接

      USE myemployees;
      #案例1,查询员工名,部门名(调换位置)
      SELECT 
        last_name,
        department_name 
      FROM
        employees e 
        INNER JOIN departments d 
          ON e.`department_id` = d.`department_id` ;
      
      #案例2,查询名字包含e的员工名和工种名(筛选)
      SELECT 
        last_name,
        job_title 
      FROM
        employees e 
        INNER JOIN jobs j 
          ON e.`job_id` = j.`job_id` 
      WHERE last_name LIKE ‘%e%‘ ;
      
      #案例3,查询部门个数大于3的城市名和部门个数(分组+筛选)
      #1. 查询每个城市的部门个数
      #2. 在1结果上筛选满足条件的
      SELECT 
        city,
        COUNT(*) 
      FROM
        departments d 
        INNER JOIN locations l 
          ON d.`location_id` = l.`location_id` 
      GROUP BY city 
      HAVING COUNT(*) > 3 ;
      
      #案例4,查询那个部门的部门员工大于3的部门名和员工个数,并且按个数降序(排序)
      SELECT 
        department_name,
        COUNT(*) 
      FROM
        employees e 
        INNER JOIN departments d 
          ON e.`department_id` = d.`department_id` 
      GROUP BY department_name 
      HAVING COUNT(*) > 3 
      ORDER BY COUNT(*) DESC ;
      
      #案例5,查询员工名,部门名,工种名,并按部门名降序
      SELECT 
        last_name,
        department_name,
        job_title 
      FROM
        employees e 
        INNER JOIN departments d 
          ON e.`department_id` = d.`department_id` 
        INNER JOIN jobs j 
          ON e.`job_id` = j.`job_id` 
      ORDER BY department_name DESC;
      
    • 非等值连接

      #查询员工的工资级别
      SELECT department_id,salary,grade_level
      FROM employees e
      JOIN job_grades j
      ON  j.`lowest_sal`<salary AND salary<j.`highest_sal`
      #on e.`salary` between j.`lowest_sal` and j.`highest_sal`
      ORDER BY grade_level ;
      #查询每个工资级别的个数>20,并且按工资级别降序
      SELECT COUNT(*),grade_level
      FROM employees e
      JOIN job_grades j
      ON e.`salary` BETWEEN j.`lowest_sal` AND j.`highest_sal`
      GROUP BY  grade_level
      HAVING COUNT(*)>20
      ORDER BY grade_level DESC;
      
    • 自连接

      #查询员工的名字,上级的名字
      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%‘;
      
  2. 外连接

    #引入:查询没有男朋友的女神名
    USE girls;
    SELECT * FROM beauty;
    SELECT * FROM boys;
    -- 左外连接
    SELECT b.name,bo.*
    FROM  beauty b
    LEFT OUTER JOIN boys bo
    ON b.`boyfriend_id`=bo.`id`
    WHERE bo.`id` IS NULL;
    -- 右外连接
    SELECT b.`name`,a.* 
    FROM boys a
    RIGHT OUTER JOIN beauty b
    ON a.`id`=b.`boyfriend_id`
    WHERE a.`id` IS NULL;
    
    #案例1:查询那个部门没有员工
    USE myemployees;
    #左外 部门主表
    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;
     
     #全外 MySQL不支持
     USE girls;
     SELECT b.*,bo.*
     FROM beauty b
     FULL OUTER JOIN boys bo
     ON b.`boyfriend_id`=bo.id;
    
  3. 交叉连接

     SELECT b.*,bo.*
     FROM beauty b
     CROSS JOIN boys bo;
    

子查询

一,where或having后面

二,select 后面

三,from后面

四,exists后面

代码实例

分页查询

代码示例

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

union联合查询

代码实例:

#引入案例:查询部门编号>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;

#案例:查询中国用户男性的信息以及外国用户男性的信息
SELECT id,cname,csex FROM t_ca WHERE csex=‘男‘
UNION
SELECT t_id,tName,tGender FROM t_ula WHERE tGender=‘male‘;

查询总结

select 查询列表		⑦
from 表1 别名		①
连接类型 join 表2	②
on 连接条件			③
where 筛选条件		④
group by 分组列表	⑤
having 筛选			⑥
order by 排序列表	 ⑧
limit 起始条目索引,条目数;  ⑨

六, DML语言的学习(Data Manipulation Language)

插入语句

修改语句

  1. 修改单表的记录

    • 语法:

      update 表名
      set 字段=新值,字段=新值,...
      where 筛选条件;
      
  2. 修改多表的记录

    • sql92语法:

      update 表1 别名,表2 别名
      set 列=值,...
      where 连接条件
      and 筛选条件;
      
    • sql99语法:

      update 表1 别名
      inner|left|right join 表2 别名
      on 连接条件
      set 列=值,...
      where 筛选条件;
      
  3. 代码实例:

    #1. 修改单表的记录
    #案例一:修改beauty表中性唐的女神的电话为13783454548
    update beauty set phone =‘13783454548‘
    where name like ‘唐‘;
    
    #案例2:修改boys表中id号为2的名称为张飞,魅力值10
    update boys set boyname=‘张飞‘,usercp=10
    where id=2;
    
    #2. 修改多表的记录
    #案例1:修改张无忌的女朋友手机号为114
    update boys bo
    inner join beauty b
    on bo.`id`=b.`boyfriend_id`
    set bo.`boyName`=‘张无忌‘;
    
    #案例2:修改没有男朋友的女神的男朋友的编号都为2号
    update boys bo 
    right join beauty b
    on bo.`id`=b.`boyfriend_id`
    set b.`boyfriend_id`=2
    where bo.`id` is null;
    
    select bo.*,b.* from boys bo 
    right join beauty b 
    on bo.`id`=b.`boyfriend_id`
    

删除语句

  1. delete

    • 单表的删除

      语法:

      delete from 表名 where 筛选条件 limit 条目数;
      
    • 多表的删除

      • sql92:

        delete 表1的别名,表2的别名
        from 表1 别名,表2 别名
        where 连接条件
        and 筛选条件;
        
      • sql99:

        delete 表1的别名,表2的别名
        from 表1 别名
        inner|left|right| join 表2 别名 
        on 连接条件
        where 筛选条件;
        
  2. truncate(不可以加where)直接删除

    语法:

    truncate table 表名;
    

    底层是先把表删除,然后在创建一张一模一样的表

  3. delete pk truncate

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

    #方式一:delete
    #1. 单表的删除
    #案例1:手机号以9结尾的女神信息
    DELETE FROM beauty 
    WHERE phone` like ‘%9‘; 
    
    #2. 多表的删除
    #案例:删除张无忌的女朋友的信息
    delete d 
    from beauty b
    inner join boys bo 
    on b.boyfriend_id=bo.id
    where bo.boyName=‘张无忌‘;
    
    #案例:删除黄晓明的信息以及他女朋友的信息
    delete b,bo
    from beauty b
    inner join boys bo
    on b.boyfriend_id=bo.id
    where bo.boyName=‘黄晓明‘;
    
    #方式二:truncate语句
    #案例1:将魅力值>100的男神信息删除
    truncate table boys;
    #不可以加筛选,只能全部清空
    

七, DDL语言的学习(Data Define Language)

库和表的管理

库的管理

  1. 库的创建create

    create database 【if not exists】 库名 【character set 字符集名】;
    
  2. 库的修改alter

    已过时5.1.1:rename database 旧库名 to 新库名; 目前不能修改库名。
    更改库的字符集:
    alter database 库名 character set gbk;
    
  3. 库的删除drop

    drop database if exists 库名;
    

表的管理

  1. 表的创建create

    create table if not exists 表名(
    	字段名 字段的类型【(长度) 约束】,
    	字段名 字段的类型【(长度) 约束】,
    	...
    	字段名 字段的类型【(长度) 约束】
    	);
    
  2. 表的修改ALTER

    ALTER TABLE 表名 ADD|DROP|MODIFY|CHANGE COLUMN 列名 【列类型 约束】;
    

    2.1. 修改列名
    ALTER TABLE 表名 CHANGE 【COLUMN】 旧列名 新列名 类型;
    2.2. 修改列的类型或约束
    ALTER TABLE 表名 MODIFY COLUMN 列名 新类型【新约束】;
    2.3. 添加新列
    ALTER TABLE 表名 ADD COLUMN 添加的列名 类型 【first|after 字段名】;
    2.4. 删除列 (只有在库和表的时候才可以使用IF EXISTS)
    ALTER TABLE 表名 DROP COLUMN 列名;
    2.5. 修改表名
    ALTER TABLE 旧表名 RENAME 【TO】 新表名;

  3. 表的删除drop

    DROP TABLE IF EXISTS 表名;
    
  4. 表的复制

    #4.1 仅仅复制表的结构
    CREATE TABLE 要复制的表名 LIKE 被复制的表名; 
    #4.2 复制表的结构+数据(可以跨库 库名打点)
    CREATE TABLE 要复制的表名 
    SELECT 列,... FROM 被复制的表名
    WHERE 筛选条件;
    

常见的数据类型介绍

数值

  1. 整形

    整数类型 字节 范围
    tinyint 1 有符号:-128~127 无符号:0~255
    smallint 2 有符号:-32768~32767 无符号:0~65535
    mediumint 3 有符号:-8388608~8388607 无符号:0~1677215 (好吧,反正很大,不用记住)
    int,integer 4 有符号:-2147483644~2147483647 无符号:0~4294967295 (好吧,反正很大,不用记住)
    bigint 8 有符号:-9223372036854775808~9223372036854775807 无符号:0~9223372036854775807*2+1 (好吧,反正很大,不用记住)

    特点:

    1. 如果不设置无符号还是有符号,默认是有符号,如果像设置无符号,需要添加 unsigned 关键子

    2. 如果插入的数值超出了整型的范围,会报out of range 异常,并且插入临界值

    3. 如果不设置长度,会有默认的长度

      长度代表了显示的最大宽度,如果不够会用0在左边填充,但必须搭配 zerofill 使用!,并且默认变为无符号整型

  2. 小数

    • 定点数

      定点类型 字节 范围
      dec(m,d) decimal(m,d) m+2 最大取值范围于double相同,给定decimal的有效取值范围有m和d决定
    • 浮点数

      浮点数类型 字节 范围
      float 4 土1.75494351E~土3.402823466E+38
      double 8 土2.2250738585072014E-308~土1.7976931348623157E+308

      特点:

      1. m和d的意思:

        m:整数部位+小数部位

        d:小数部位(不够补零,多出四舍五入)

        如果超出范围,会报out or range异常,并且插入临界值

      2. d和m都可以省略

        如果是decima,则m默认为10,D默认为0

        如果是float和double,则会根据插入的数值的精度来决定精度

      3. 定点型的精确度较高,如果插入数值的精度较高如货币运算等则考虑使用

原则

字符

日期

日期和时间类型 字节 最小值 最大值
date 4 1000-01-01 9999-12-31
datetime 8 1000-01-01 00:00:00 9999-12-31 23:59:59
timestamp 4 1970010180001 2038年的某个时刻
time 3 -838:59:59 838:59:59
year 1 1901 2155

常见的约束

标识列

#一, 创建表时设置标识列
drop table if exists table_identity;
create table tab_identity(
	id int primary key auto_increment,#添加主键自增
    name varchar(20)
);
truncate table tab_identity;#清空表中数据
insert into tab_identity(id,name) values (null,‘john‘);
insert into tab_identity(name) values (‘lucy‘);

show variables like ‘%auto_increment%‘;#查看自增长值,起始值设置了没有效果,步长可以设置
set auto_increment_increment=3;#设置步长
#二, 修改表时设置标识列
alter table tab_identity modify column id int primary key auto_increment;
#三, 修改表时删除标识列
alter table tab_identity modify column id int;

八, TCL语言的学习(Transaction Control Language)

事物和事物处理

九, 视图的讲解

一,含义

二,创建

三,修改

四,删除

五,查看

六,使用

  1. 插入(和表的语法一样)
    insert into 视图名 【(字段)】 values (值,...);
  2. 修改
    update 视图名 set 修改的字段=‘值‘ where 筛选条件;
  3. 删除
    delete 视图名 where 筛选条件;
  4. select 字段 from 视图名;

七,视图和表的对比

创建语法的关键字 是否实际占用物理空间 使用
视图 create view 只保存了sql逻辑 增删改查,一般不能增删改
create table 保存了数据 增删改查

十, 变量

代码:

#一,系统变量
#1》全局变量
#①查看所有的全局变量
SHOW GLOBAL VARIABLES;
#②查看部分的全局变量
SHOW GLOBAL VARIABLES LIKE ‘%char%‘;
#③查看指定的全局变量的值
SELECT @@global.autocommit;#查看自动提交(1默认自动提交)
SELECT @@tx_isolation;#查看隔离级别
#④为某个指定的全局变量赋值
SET @@global.autocommit=1;

#2》会话变量
SHOW SESSION VARIABLES;
SHOW  VARIABLES;
#②查看部分的会话变量
SHOW VARIABLES LIKE ‘%char%‘;
#③查看指定的某个会话变量
SELECT @@session.tx_isolation;#查看隔离级别
SELECT @@tx_isolation;
#④为某个会话变量赋值
方式一:
SET @@session.tx_isolation=‘read-uncommitted‘;#设置隔离级别
SET @@tx_isolation=‘read-uncommitted‘;
方式二:
SET SESSION tx_isolation=‘read-committed‘;

#二,自定义变量
#1. 用户变量
#案例
#声明并初始化
SET @name=‘john‘;
SET @name=100;
SET @count=1;
#赋值
SELECT COUNT(*) INTO @count
FROM employees;
#查看
SELECT @count;

#2. 局部变量
#案例:声明两个变量并赋初始值,并求和,并打印
#1. 用户变量
SET @m=1;
SET @n=2;
SET @sum=@m+@n;
SELECT @sum;
#2. 局部变量
DECLARE m INT DEFAULT 1;
DECLARE n INT DEFAULT 2;
DECLARE SUM INT ;
SET SUM=m+n;
SELECT SUM;

十, 存储过程和函数

存储过程

代码:

#一,创建
#1. 空参列表cmd中使用
#案例:插入到admin表中五条记录
SELECT * FROM admin;

DELIMITER $ #结束标记
CREATE PROCEDURE myp1()
BEGIN 
  INSERT INTO admin(username,`password`) 
  VALUES (‘john1‘,‘0000‘),(‘lily‘,‘0000‘),(‘rose‘,‘0000‘),(‘jack‘,‘0000‘),(‘tom ‘,‘0000‘);
END $

#调用
CALL myp1()$
#查看
SELECT * FROM admin$

#2. 创建带in模式参数的存储过程
#案例1:创建存储过程实现 根据女神名,查询对应的男神
CREATE PROCEDURE myp2(IN beautyName VARCHAR(20))
BEGIN 
  SELECT bo.*
  FROM boys bo
  RIGHT JOIN beauty b
  ON bo.`id`=b.`boyfriend_id`
  WHERE b.`name`=beautyName;
END $

#调用 
CALL myp2(‘Angelababy‘)$
#如果出现 incorrect string value 是与字符集有关,需要设置字符集
#set names gbk$

#案例2:创建存储过程实现,用户是否登陆成功
CREATE PROCEDURE myp3(IN username VARCHAR(20),IN PASSWORD VARCHAR(20))
BEGIN 
  DECLARE result INT DEFAULT 0;#申明局部变量并初始化
  
  SELECT COUNT(*) INTO result #赋值
  FROM admin
  WHERE admin.`password`=username
  AND admin.`password`=PASSWORD;
  
  SELECT IF (result>0,‘成功‘,‘失败‘);#使用
END $
#调用
CALL myp3(‘lyt‘,‘6666‘)$

#3. 创建带out模式的存储过程
#案例1:根据女神名,返回对应的男神名(返回一个)
CREATE PROCEDURE myp4(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20))
BEGIN
  SELECT bo.boyName INTO boyName#给返回值赋值
  FROM boys bo
  INNER JOIN beauty b 
  ON bo.id=b.boyfriend_id
  WHERE b.name=beautyName;
END $
#调用
#set @bName$ #定义变量(可以不定义直接用)
CALL myp4(‘唐艺昕‘,@bName)$#调用
SELECT @bName$ #查看

#案例2:根据女神名,返回对应的男神名和男神魅力值(两个返回值)
CREATE PROCEDURE myp5(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT userCP INT)
BEGIN 
  SELECT bo.boyName,bo.userCP INTO boyName,userCP
  FROM boys bo
  INNER JOIN beauty b 
  ON bo.id=b.boyfriend_id
  WHERE b.name=beautyName;
END $
#调用
CALL myp5(‘唐艺昕‘,@bName,@usercp)$
SELECT @bName,@usercp$

#4. 创建带inout模式参数的存储过程
#案例1.传入a和b两个值,最终a和b都翻倍并返回
CREATE PROCEDURE myp6(INOUT a INT ,INOUT b INT)
BEGIN 
  SET a=a*2;
  SET b=b*2;
END
#使用
#先定义两个变量
SET @m=10$
SET @n=20$
CALL myp6(@m,@n)$#调用方法
#查看值
SELECT @m,@n$

#二,删除存储过程
DROP PROCEDURE `myp2`;
DROP PROCEDURE `myp3`;
DROP PROCEDURE `myp4`;
DROP PROCEDURE `myp5`;
#三,查看存储过程的信息
SHOW CREATE PROCEDURE  存储过程名;

#-----------------------------------------------总和案例:
#一,创建存储过程实现传入用户名和密码,插入到admin表中
CREATE PROCEDURE test_p1(IN username VARCHAR(20),IN loginpwd VARCHAR(20))
BEGIN
  INSERT INTO admin(admin.username,PASSWORD)
  VALUES(username,loginpwd);
END $
#二,创建存储过程实现出啊如女神编号,返回女神名称和女神电话
CREATE PROCEDURE test_p2 (IN id INT,OUT NAME VARCHAR(20),OUT phone VARCHAR(20))
BEGIN
  SELECT b.name,b.phone INTO NAME,phone
  FROM beauty b
  WHERE b.id=id;
END $
#三,创建存储过程或函数实现传入两个女神生日,返回大小
CREATE PROCEDURE test_p3(INT bir1 DATETIME,INT bir2 DATETIME,OUT result INT)
BEGIN
  SELECT DATEDIFF(bir1,bir2) INT reslt;
END $
#四,创建存储过程或函数实现传入一个日期,格式化成XXX年XX月XX日并返回
CREATE PROCEDURE test_p4(IN mydate DATETIME,OUT strDate VARCHAR(50))
BEGIN
  SELECT DATE_FORMAT(mydate,‘%y年%m月%d日‘) INTO strDate;
END $
CALL test_p4(NOW(),@str)$
SELECT @str $
#五,传入:小昭		返回:小昭 and 张无忌
CREATE PROCEDURE test_p5(IN beautyName VARCHAR(20),OUT str VARCHAR(50))
BEGIN
  SELECT CONCAT(beautyName,‘ and ‘,IFNULL(boyName,‘null‘)) INTO str
  FROM boys bo
  RIGHT JOIN beauty b 
  ON b.boyfriend_id=bo.id
  WHERE b.name=beautyName;
END $
CALL test_p5(‘柳岩‘,@str)$
SELECT @str $
#六,创建存储过程或函数,根据传入的条目数和其实索引,查询beauty表的记录
CREATE PROCEDURE test_p5(IN startIndex INT,IN size INT)
BEGIN
  SELECT * FROM beauty LIMIT startIndex,size;
END $
test_p5(3,3)$

函数

代码

#------------------案例演示
#1. 无参有返会
#案例:返回公司的员工个数
DELIMITER $ #设置结束标记
CREATE FUNCTION myf1() RETURNS INT
BEGIN
  DECLARE c INT DEFAULT 0;#定义局部变量
  SELECT COUNT(*) INTO c#赋值
  FROM employees;
  RETURN c;
END $
SELECT myf1()$ #调用

#2. 有参有返
#案例1:根据员工名,返回它的工资
CREATE FUNCTION myf2(empName VARCHAR(20)) RETURNS DOUBLE
BEGIN
  SET @sal=0;#定义用户变量
  SELECT salary INTO @sal #赋值
  FROM employees
  WHERE last_name= empName;
  RETURN @sal;
END $
SELECT myf2(‘Kochhar‘)$

#案例2:根据部门名,返回该部门的平均工资
CREATE FUNCTION myf3(d_name VARCHAR(15)) RETURNS DOUBLE
BEGIN
  DECLARE s DOUBLE DEFAULT 0.0;#定义局部变量
  SELECT AVG(salary) INTO s
  FROM employees e
  INNER JOIN departments d
  ON e.department_id = d.department_id
  WHERE d.department_name=d_name;
  RETURN s;
END $
SELECT myf3(‘IT‘)$

#三,查看函数
SHOW CREATE FUNCTION myf3$

#四,删除函数
DROP FUNCTION myf1;

#案例
#一,创建函数,实现传入两个float,返回二者只和
CREATE FUNCTION test_f1(num1 FLOAT,num2 FLOAT) RETURNS FLOAT
BEGIN	
  DECLARE SUM FLOAT DEFAULT 0;
  SELECT SUM=num1+num2;
  RETURN SUM;
END $
SELECT test_f1(1,2)$

十一, 流程控制结构

```mysql
### 顺序结构

- 程序从上往下一次执行

### 分支结构

- 程序从两条或多条路径中选择一条去执行

1. if函数

 功能:实现简单的双分支
 语法:select if(表达式1,表达式2,表达式3)
 执行顺序发:如果表达式1成立,则if函数返回表达式2的值,否则返回表达式3的值
 应用:任何地方

2. case结构

 - 类似于Java中的switch语句,一般用于实现等值判断

   语法:

     ```mysql
   	case 变量|表达式|字段
   	when 要判断的值 then 返回的值1或语句1;
   	when 要判断的值 then 返回的值1或语句2;
   	...
   	else 要返回的值n或语句n;
   	end case;
  1. if结构

    功能:实现多重分支

    语法:

    if 条件1 then 语句1;
    elseif 条件2 then 语句2;
    ...
    end if;
    

    应用场合:应用在begin end中

循环结构

  1. while

    语法:

    【标签:】while 循环条件 do
    循环体;
    end while【标签】;
    

    特点:先判断后执行
    位置:begin end中

  2. loop

    语法:

    【标签:】loop
    循环体;
    end loop 【标签】;
    

    特点:没有条件的死循环
    位置:begin end中

  3. repeat

    语法:

    【标签:】 repeat
    循环体;
    until 结束循环的条件
    end repeat 【标签】;
    

    特点:先执行后判断
    位置:begin end中

代码:

#2. case结构
#案例:
#创建存储过程,根据传入的成绩,来显示等级,比如传入的成绩:90-100 显示A,80-90 显示B,80-60 C,否则显示D
DELIMITER $ #定义结束标记
CREATE PROCEDURE test_case (IN score INT)
BEGIN 
	CASE 
	WHEN score>=90 AND score<=100 THEN SELECT ‘A‘;
	WHEN score >=80 THEN SELECT ‘B‘;
	WHEN score >=60 THEN SELECT ‘C‘;
	ELSE SELECT ‘D‘;
	END CASE;
END $
#调用存储过程
CALL test_case(66)$

#3. if结构
#案例1:根据传入的成绩,来显示等级,比如传入的成绩:90-100 返回A,80-90 返回B,80-60 C,否则返回D
CREATE FUNCTION test_if(score INT) RETURN CHAR
BEGIN
	IF score>=90 AND score<=100 THEN RETURN ‘a‘;
	ELSEIF score>=80 THEN RETURN ‘b‘;
	ELSEIF score>=60 THEN RETURN ‘c‘;
	ELSE RETURN ‘d‘;
	END IF; 
END $
#调用
SELECT test_if(88)$


#二,循环结构
#1. 没有添加循环控制语句
#案例:批量插入,根据次数插入到admin表中多条记录
CREATE PROCEDURE pro_while1 (IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 1;#定义局部变量默认为1
	WHILE i<insertCount DO
		INSERT INTO admin(username,`password`) VALUES(CONCAT(‘Rose‘,i),‘666‘);
		SET i=i+1;#设置自增条件
	END WHILE;
END$
#调用
CALL pro_while1(100)$

#2. 添加leave语句
#案例:批量插入,根据次数插入到admin表中多条记录,如果次数>20则停止
TRUNCATE TABLE admin$ #删除库中的数据
DROP PROCEDURE test_while1$#删除存储过程
CREATE PROCEDURE test_while1(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 1;#定义局部变量默认为1
	a:WHILE i<=insertCount DO
		INSERT INTO admin(username,`password`) VALUES(CONCAT(‘xiaoha‘,i),‘0000‘);
		IF i>=20 THEN LEAVE a;#结束循环
		END IF;
		SET i=i+1;#自增
	END WHILE a;
END $
#调用
CALL test_while1(100)$

#3. 添加iterate语句
#案例:批量插入,根据次数插入到admin表中多条记录,只插入偶数次
TRUNCATE TABLE admin$ #删除库中的数据
DROP PROCEDURE test_while1$#删除存储过程
CREATE PROCEDURE test_while1(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 0;#定义局部变量默认为1
	a:WHILE i<=insertCount DO
		SET i=i+1;#自增
		IF MOD(i,2)!=0 THEN ITERATE a;#跳出本次循环
		END IF;
		INSERT INTO admin(username,`password`) VALUES(CONCAT(‘xiaoha‘,i),‘0000‘);
	END WHILE a;
END $

CALL test_while1(100)$  

#-----------------------------------流程控制经典题--------------------------------
/*
一,已知表stringcontent
其中字段:
id 自增长
content varchar(20)

向该表插入指定个数的,随机的字符串
*/
DROP TABLE IF EXISTS stringcontent;
CREATE TABLE stringcontent(
	id INT PRIMARY KEY AUTO_INCREMENT,
	content VARCHAR(20)
);
DELIMITER $
CREATE PROCEDURE test_randstr_insert(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 1;#定义一个循环变量i,表示插入次数
	DECLARE str VARCHAR(26) DEFAULT ‘abcdefghigklimopqrstuvwxyz‘;
	DECLARE startIndex INT DEFAULT 1;#代表起始索引
	DECLARE len INT DEFAULT 1;#代表截取的字符的长度
	WHILE i<=insertCount DO
		SET len=FLOOR(RAND()*(20-startIndex+1)+1);#产生一个随机的整数,代表 截取长度,1-(26-startIndex+1)
		SET startIndex=FLOOR(RAND()*26+1);#产生一个随机的整数,代表起始索引1-26
		INSERT INTO stringcontent(content) VALUES (SUBSTR(str,startIndex,len));
		SET i=i+1;#循环变量更新
	END WHILE;
END$
评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!