初始数据库

MySQL

MySQL常用语句

1.简单查询
  1. 查询表中的所有记录

    select * from 表名;

  2. 基础查询

    • 多个字段的查询
      select 字段名1,字段名2… from 表名;用SQLyog时可以用鼠标点击则表名会自动上到控制台上;用Navicat则只能用星号查询所有字段或者按个输入;注意:如果查询所有字段,则可以使用*来替代字段列表。

    • 去除重复:
      distinct

    • 计算列
      一般可以使用四则运算计算一些列的值。(一般只会进行数值型的计算)
      ifnull(表达式1,表达式2):null参与的运算,计算结果都为null
      表达式1:哪个字段需要判断是否为null
      如果该字段为null后的替换值。

    • 起别名:
      as(可以省略)

    • 显示表的结构:

      DESC + 表名。

  3. 注意事项:

    +号在MySQL中只能作为运算符,不可以用作连接符,用加号运算时,只要有乙方为字符型,则试图把字符型转为数值型,成功则运算,失败则结果为0

    需要连接时,专门用一个函数,concat 然后用小括号把两个表名括起来然后用逗号隔开

2.条件查询
  1. 语法:

    select 查询列表 from 表名 where 筛选条件;(筛选条件为判断语句如结果为true则显示结果,如为false则不在界面上显示)

  2. 分类:

    • 按条件表达式筛选

      条件运算符:> < = <> >= <=

    • 按逻辑表达式查询:

      逻辑运算符:&& || !,and or not

      &&和and: 两个条件都为true,结果为true,反之则为false

      ||和or: 只要有一个条件为true,结果为true,反之为false

      !和not: 如果连接的条件本身为false,结果为true,反之为false

    • 模糊查询:

      like:按某个字符,或某几个字符来筛选,一般来讲和通配符搭配使用

      ​ 通配符:

      ​ % 任意多个字符

      ​ __ 任意单个字符

      between and:筛选在两个数值之间的条件,

      ​ 特点:区间值是包含的,等同于>=和<=;两个临界值不能颠倒;

      ​ 如果是不在两个数值之间,就是 not between 数值 and 数值

      in: 用于去判断某字段的值是否属于in列表中的某一项

      ​ 特点:相对于or提高简洁度;in列表中的值类型必须一致或兼容;不支持通配符

      is null:=和<>不能判断null值,is null可以判断null值但是不能判断普通的值

    • 安全等于

      <=>:可以判断null值,也可以判断普通的值

  3. 案例:

    • 案例一:按条件表达式筛选

      查询部门编号不等于90号的员工名和部门编号

      SELECT 
      		last_name,
              department_id
      FROM 
      		employees 
      WHERE 
      		department_id<>90; 
      
    • 案例二: 按逻辑表达式筛选

      查询 工资z在10000和20000的员工名,工资以及奖金

      SELECT
      		last_name,
      		salary,
      		commission_pct
      FROM
      		employees
      WHERE
      		salary>=10000 AND salary<=20000;
      
    • 案例三:模糊查询

      like::

      例1:查询员工名中包含字符a的员工信息

      SELECT
      		*
      FROM
      		employees
      WHERE
      		last_name LIKE  '%a%';
      

      例2:查询员工名中第三个字符为e,第五个字符为a的员工名和工资

      SELECT
      		last_name,
      		salary
      FROM
      		employees
      WHERE
      		last_name LIKE '__e_a%';
      

      例3:查询员工名中第二个字符为_的员工名

      SELECT
      		last_name
      FROM
      		employees
      WHERE
      		last_name LIKE '_$_%' ESCAPE '$';#escape为指定转译符号,防止_被算作通配符
      

      between and::

      例1:查询员工编号在100到120之间的员工信息

      SELECT
      		*
      FROM
      		employees
      WHERE
      		employee_id BETWEEN 100 AND 120;
      

      in::

      例1:查询员工的工种编号是 IT_PROG、AD_VP、AD_PRES中的哟个的员工名和工种编号

      SELECT
      		last_name,
      		job_id
      FROM
      		employees
      WHERE
      		job_id IN('IT_PROT','AD_VP','AD_PRES');
      

      is null::

      例1:查询没有奖金的员工名和奖金率

      SELECT
      		last_name,
      		commission_pct
      FROM
      		employees
      WHERE
      		commission_pct IS NULL;
      

      例:查询有奖金的员工名和奖金率

      SELECT
      		last_name,
      		commission_pct
      FROM
      		employees
      WHERE
      		commission_pct IS NOT NULL;
      

排序&分组查询

1.排序
  1. 语法:

    SELECT	查询列表
    fromwhere	筛选条件
    order by 排序列表  asc(升序)|desc(降序)不写默认升序
    

    1.order by 子句中可以支持单个字段,多个字段,表达式,函数,别名

    2.order by子句一般放在查询语句的最后面,limit子句除外

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

    select * from employees order by salary desc;
    

    案例2:查询部门编号>=90的员工信息,按入职时间的先后进行排序

    select *
    from employees
    where department_id>=90
    order by hiredate asc;
    

    案例3:按年薪高低显示员工的信息和年薪(按表达式排序)

    select *,salaty*12*(1+IF NULL(commission_pct,0))
    from employees
    order by salaty*12*(1+IF NULL(commission_pct,0)) desc;
    

    案例4:按年薪高低显示员工的信息和年薪(按别名排序)

    select *,salaty*12*(1+IF NULL(commission_pct,0)) 年薪
    from employees
    order by 年薪 desc;
    

    案例5:按姓名的长度显示员工的姓名和工资(按函数排序)

    select LENGTH (last_name)字节长度,last_name,salary;
    from employees
    order by length (last_name) desc
    

    案例6:查询员工信息,要求先按工资排升序,再按员工编号排降序

    select *
    from employees
    order by salary asc,employee_id desc; 
    
2.常见函数
  • 概念 :类似于Java的方法,将一组逻辑语句封装在方法体中,对外暴露方法名

  • 好处:1,隐藏了实现细节 2,提高了代码的重用性

  • 调用:select 函数名() from 表 ;

  • 特点:

    1. 叫什么(函数名)
    2. 干什么(函数功能)
  • 分类:

    1. 单行函数

      如 concat、length、ifnull等

    2. 分组函数

      功能:做统计使用,又叫统计函数,聚合函数,总称组函数

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

      select length(‘john’);

      select length(‘张三丰hahaha’)

    2. concat: 拼接字符串

      SELECT CONCAT(last_name,’_’,first_name) FROM employees;

    3. upper、lower

      select upper(‘john’);变字符串大写

      select lower(‘john’);变字符串小写

      示例:将姓变大写,名变小写,然后拼接

      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)))
      
    5. instr:返回字串第一次出现的索引,如果找不到则返回0

    6. trim:

      select length(trim('     123     ')) as out_put
      #会去掉空格
      select trim('a' from 'aaaaaaa1aaaaaaaaa23aaaaaaaa') as out_put;
      #会去掉两边的字符
      
    7. lpad:用指定的字符实现左填充指定长度,最后长度会和输入长度相同

      select lpad('殷素素',10,'*')
      
    8. rpad:右填充。

    9. replace: 替换

      select replace('1233454634','1','5');
      
2.数学函数
  1. round:四舍五入

    select round(-1.55);#结果为2
    select round(1.456,2);#小数点后保留两位
    
  2. ceil:向上取整,返回大于等于该参数的最小整数

    select ceil(1.002);#结果为2
    select ceil(-1.002);#结果为-1
    
  3. floor:向下取整,返回小于等于该参数的最大整数

    select floor(-9.99);#10
    
  4. truncate:截断

    select truncate(1.23333,1);#保留小数后一位,1.2
    
  5. mod:取余

    select mod(10,3);#1
    select mod(-10,-3);#-1
    select mod(10,-3);#1
    
3.日期函数
  1. now:返回当前系统日期+时间

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

    select curdate();
    
  3. curtime:返回当前系统时间,不包含日期

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

    select year(now()) ;
    select year('1998-1-1')
    
    select year(hiredate)from employees
    
    select month(now()) ;
    
  5. str_to_date:将字符通过指定的格式转换成日期

    select str_to_date('1998-3-2','%Y-%c-%d');
    
  6. date_formant:将日期转换成字符

    select date_format(now(),'%y年%m月%d日');
    
  7. datediff:计算两个日期之间的差

4.其他函数

select version(); 查看版本号

select database(); 查看当前数据库

select user(); 查看当前用户

5.流程控制函数
  1. if函数 :if else的效果

    select if(10>5,'大','小');
    
    select last_name,commission_pct,if(commission_pct is null,'没奖金','有奖金') from employees;
    
  2. case函数:

    使用一:类似于switch case 的效果

    case  要判断的字段或者表达式
    when  常量1  then 要显示的语句1;
    when  常量2  then 要显示的语句2;
    ...
    else 要显示的值或语句;
    end
    

    案例:查询员工的工资,要求

    ​ 部门号=30,显示的工资为1.1倍

    ​ 部门号=40,显示的工资为1.2倍

    ​ 其他部门显示的为原有工资

    select salary 原始工资,department_id,
    case department_id
    when 30 then salary*1.1
    when 40 then salary*1.2
    else salary
    end as 新工资
    from employees;
    

    使用二:类似于多重if

    case 
    when 条件1 then 要显示的值1或语句1;
    when 条件2 then 要显示的值2或语句2;
    ...
    else 要显示的值n或语句n;
    end
    

    案例:查询员工的工资情况

    工资>20000,显示A级别

    工资>15000,显示B级别

    工资>10000,显示C级别

    否则显示D级别

    select salary,
    CASE
    WHEN salary>20000 then 'A'
    when salary>15000 then 'B'
    when salary>10000 then 'C'
    else 'D'
    end as 工资级别
    from employees; 
    
3.分组函数
  • 功能:用作统计使用,又称为聚合函数或统计函数和组函数

  • 分类:sum 求和、avg 平均值、max 最大值、min 最小值、count 计算个数

  • 特点:1、sum、avg一般用于处理数值型

    ​ max、min、count 可以处理任何类型

    ​ 2、以上分组函数都忽略null值

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

    ​ select sum(distinct salary),sum(salary) from employees;

    ​ 4、count的单独介绍:

    ​ 一般使用count(*)统计行数

    select count(salary) from employees;
    
    select count(*) from employees;#只要每列有null就不会统计
    
    select count(1) from employees;#相当于统计了有多少行
    

    ​ 效率:myisam存储引擎下,count(*)的效率高

    ​ innodb存储引擎下,count(*)和count(1)的效率差不多,比count(字段)要高一些

    ​ 5、和分组函数一同查询的字段要求是group by后的字段

  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;
    
4.分组查询

语法:

select 分组函数,列(要求出现在group by的后面)
from[where  筛选条件]
group by 分组的列表
order by 子句
注意:
查询列表必须特殊,要求是分组函数和group by后出现的字段
特点:
分组查询中的筛选条件分为两类
					数据源					位置					关键字
	分组前筛选		原始表					group by子句的前面		where
	分组后筛选		分组后的结果集			 group by子句的后面		 having
	
	分组函数分组函数做条件肯定是放在having子句中
	能用分组前筛选的,就优先考虑使用分组前筛选

引入:查询每个部门的员工工资

select avg(salary) from employees;

案例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 manager_id

添加分组后的筛选条件

案例1:查询哪个部门的员工个数大于2

select count(*),department_id
from employees
group by department_id
having count(*)>2

案例2:查询每个工种有奖金的员工的最高工资大于12000的工种编号和最高工资

select max(salary),job_id
from employees
where commission_put is not null
group by job_id
having max(salary)>12000;

案例3:查询领导编号大于102的每个领导手下的最低工资大于5000的领导编号是哪个,以及其最低工资

select min(salary),manager_id
from employees
where manager_id>102
group by manager_id
having min(salary)>5000

按表达式或函数分组

案例:按员工姓名的长度分组,查询每一组的员工个数,查询员工数大于5的有哪些

1 查询每个长度的员工个数
select count(*),length(last_name) len_name
from employees
group by length(last_name)
2 添加筛选条件
select count(*),length(last_name) len_name
from employees
group by length(last_name)
having count(*)>5

按多个字段分组

案例:查询每个部门每个工种的员工的平均工资

select avg(salary),department_id,job_id
from rmployees
group by department_id,job_id

添加排序

案例:查询每个部门每个工种的员工的平均工资,并且按平均工资的高低显示出来

select avg(salary),department_id,job_id
from rmployees
group by department_id,job_id
order by avg(salary) desc;

连接查询

含义:又称多表查询,当查询的字段来自多个表时,就会用到连接查询

笛卡尔乘积现象:表1 有m行,表2有n行,结果=m*n行

发生原因:没有有效的连接条件

如何避免:添加有效的连接条件

分类:

​ 按年代分类:

​ sql92标准:仅仅支持内连接

​ sql99标准【推荐】:支持内连接和外连接(左外和右外)

​ 按功能分类:

​ 内连接:等值连接

​ 非等值连接

​ 自连接

​ 外连接:左外连接

​ 右外连接

​ 全外连接

​ 交叉连接

一、sql192标准
1、等值连接

多表等值连接的结果为多表的交集部分

n表连接,至少需要n-1个连接条件

多表的顺序没有要求

一般需要为表起别名

可以搭配前面介绍的所有子句使用,比如排序、分组、筛选

  1. 案例1:查询女生名对应的男生名

    select name,boyName
    from boys,beauty
    where beauty.boyfriend_id= boys.id;
    
  2. 案例2:查询员工名和对应的部门名

    select last_name,department_name
    from employees,departments
    where employees.'department_id'=departments.'department_id';
    
1、为表起别名

1.提高语句的简洁度

2.区分多个重名的字段

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

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

select last_name,e.job_id,j.job_title
from employees  e,jobs  j
where e.job_id=j.job_id;
2、两个表的顺序可以调换

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

select last_name,e.job_id,j.job_title
from jobs  j,employees  e
where e.job_id=j.job_id;
#没有影响
3、可以加筛选

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

select last_name,department_name,commission_pct
from employees e,departments d
where e.department_id = d.department_id
and e.commission_pct is not null;

案例2:查询城市名中第二个字符为o的部门名和城市名

select department_name,city
from departments d,locations l
where d.location_id = l.location_id
and city like'_o%';
4、可以加分组

案例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 departments d,employees e
where d.department_id=e.department_id
and commission_pct is not null
group by department_name,d.manager_id;
5、可以加排序

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

select job_title,count(*)
from employees e,jobs j
where e.job_id=j.job_id
group by job_title
order by count(*) desc;
6、可以实现三表连接

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

select last_name,department_name,city
from employees e,departments d,locations l
where e.department_id = d.dopartment_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;
3、自连接

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

select last_name,e.employee_id,m.employee_id,last_name
from  employees e;employees m
where e.manager_id = m.employee_id
二、sql99语法

语法:

​ select 查询列表

​ from 表1 别名 【连接类型】

​ jojn 表2 别名

​ on 连接条件

​ 【where 筛选条件】

​ 【group by 分组】

​ 【having 筛选条件】

​ 【order by 排序列表】

分类:

内连接:inner

外连接:

​ 左外:left 【outer】

​ 右外:right 【outer】

​ 全外:full 【outer】

交叉连接:cross

1.内连接

语法:

select 查询列表
from1 别名
inner join2 别名
on 连接条件;

分类:

等值

特点:添加排序、分组、筛选

​ inner 可以省略

​ 筛选条件放在where后面,连接条件放在on后面,提高了分离性,便于阅读

​ inner join连接和sql92语法中的等值连接效果时一样的,都是取两个表的交集部分

非等值

自连接

1.等值连接

案例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 e.last_name like '%e%';

案例3:查询部门个数大于3的城市名和部门个数,(添加分组+筛选)

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 count(*),department_name
from employees e
inner join departments d
on d.department_id = e.department_id
group by d.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 d.department_name desc;
2.非等值连接

查询员工的工资等级

select salary,grade_level
from employees e
join job_grades g
on e.salary between g.lowest_sal and g.highest_sal

查询工资级别个数大于二的个数,并且按工资级别降序

select count(*),grade_level
from employees e
join job_grades g
on e.salary between g.lowest_sal and g.highest_sal
group by grade_level
having couunt(*)>2
order by grade_level desc;
3.自连接

查询员工的名字,上级的名字

select e.last_name,m.last_name
from employees e
join employees m
on e.manager_id = m.employee_id;
二、外连接

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

特点:

1、外连接的查询结果为主表中的所有记录

​ 如果从表中有和它匹配的,则显示匹配的值

​ 如果从表中没有和它匹配的,则显示null值

​ 外连接查询结果=内连接结果+主表中有而从表中没有的记录

2、左外连接,left join 左边的是主表

​ 右外连接,right join 右边的是主表

3、左外和右外交换两个表的顺序,可以实现同样的效果

4、全外连接=内连接的结果+表1中有但表2没有的+表2中有但表1中没有的

select b.name,bo.*
from beauty b
left outer join boys bo
on b.boyfriend_id = bo.id
where bo.id is null;

案例1:哪个部门没有员工

左外:

select d.*,e.employee_id
from departments d
left outer join employees e
on d.department_id = e.department_id
where e.employee_id is null

右外:

select d.*,e.employee_id
from employees e
right outer join departments d
on d.department_id = e.department_id
where e.employee_id is null

全外:

use girls;
select b.*,bo.*
from beauty b
full outer join boys bo
on b.boyfriend_id = bo.id;

交叉连接:

select b.*,bo.*
from beauty b
cross join boys bo;
sql92和sql99

功能:sql99支持的较多

可读性:sql99实现连接条件和筛选条件的分类,可读性较高

子查询

含义:出现在其他语句中的select语句,称为子查询或内查询

外部的查询语句,称为主查询或外查询

分类:

按子查询出现的位置:

​ select后面:仅仅支持表量子查询

​ from后面:支持表子查询

​ where或having后面:支持标量子查询(单行子查询)、列子查询(多行子查询)、行子查询

​ exists后面(相关子查询):表子查询

按结果集的行列数不同:

​ 标量子查询(结果集只有一行一列)

​ 列子查询(结果集只有一列对行)

​ 行子查询(结果集有一行多列)

​ 表子查询(结果集一般为多行多列)

一、where或having后面

特点:

  1. 子查询放在小括号内

  2. 子查询一般放在条件的右侧

  3. 标量子查询,一般搭配着单行操作符使用:> < >= = <=

    列子查询,一般搭配着多行操作符使用

    in、搭配多行子查询括号里放查询语句,查询的结果为多个常量

    any/some、和子查询返回的某一个值比较,可以用其他语句代替,一般不常用

    all、和子查询返回的所有值比较

  4. 子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果

1、标量子查询(单行子查询)

案例1:谁的工资比Abel高?

select *
from employees
where salary>(
    select salary
	from employees
	where last_name = 'Abel'
)

案例2:返回job_id与141号员工相同,salary比143号员工多的员工姓名,job_id和工资

select last_name,job_id,salary
from employees
where job_id = (
	select job_id
	from employees
	where employee_id = 141
) and salary>(
	select salary
	from employees
	where employee_id = 143
)

案例3:返回公司工资最少的员工的last_name,job_id,和salary

select last_name,job_id,salary
from employees
where salary = (
	select min(salary)
    from employees
)

案例4:查询最低工资大于50号部门最低工资的部门id和其最低工资

select department_id,min(salary)
from employees
group by department_id
having min(salary)>(
	select min(salary)
    from employees
    where department_id = 50
)

非法使用标量子查询

指括号内的子查询不是一行一列

select department_id,min(salary)
from employees
group by department_id
having min(salary)>(
	select salary
    from employees
    where department_id = 50
)

select department_id,min(salary)
from employees
group by department_id
having min(salary)>(
	select salary
    from employees
    where department_id = 250
)
2、列子查询(多行子查询)

案例1:返回location_id是1400或1700的部门中的所有员工姓名

select last_name
from employees
where department_id in(
	select distinct department_id
    from departments
    where location_id in(1400,1700)
)

案例2:返回其他工种中比job_id为IT_PROG部门任意工资低的员工的员工号、姓名、job_id以及salary

select last_name,employee_id,job_id,salary
from employees
where salary< any(
	select salary
    from employees
    where job_id = 'IT_PROG'
)and job_id<>'IT_PROG';select last_name,employee_id,job_id,salary
from employees
where salary< (
	select max(salary)
    from employees
    where job_id = 'IT_PROG'
)and job_id<>'IT_PROG';

案例3:返回其他部门中比job_id为‘IT_PROG’部门所有工资都低的员工的员工号、姓名、job_id以及salary

select last_name,employee_id,job_id,salary
from employees
where salary< all(
	select salary
    from employees
    where job_id = 'IT_PROG'
)and job_id<>'IT_PROG';select last_name,employee_id,job_id,salary
from employees
where salary< (
	select min(salary)
    from employees
    where job_id = 'IT_PROG'
)and job_id<>'IT_PROG';
3、行子查询(多列多行)

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

select *
from employees
where employee_id = (
	select min(employee_id)
	from employees
)and(
	select max(salary)
	from employees
)
行子查询
select *
from employees
where (employee_id,salary) = (
	select min(employee_id),max(salary)
    from employees
)
二、select后面

仅仅支持标量子查询

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

select d.*,(
    select count(*) 
    from employees e
    where e.department_id = d.department_id
    )个数
    from departments d;

案例2:查询员工号=102的部门名

select (
	select department_name
    from departments d
    inner join employees e 
    on d.department_id = e.department_id
    where e.employee_id = 102
)
三、from后面

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

案例:查询每个部门的平均工资的工资等级

select ag_dep.*,g.grade_level
from (
        select avg(salary) ag,department_id
        from employees
        group by department_id
) ag_dep
inner join job_grades g
on ag_dep.ag between lowest_sal and highest_sal
四、exists后面(相关子查询)

语法:

exists(完整的查询语句)

结果:1或0

select exists(select employee_id from employees);

案例1:查询有员工的部门名

select department_name
from departments d
where exists(
	select *
    from employees e
    where d.department_id = e.department_id
)
#in
select department_name
from departments d
where d.department_id in(
		select department_id
    	from employees
)

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

#in
select bo.*
from boys bo
where bo.id not in (
		select boyfriend_id
    	from beauty
)

#exists
select bo.*
from boys bo
where not exists(
		select boyfriend_id
    	from beauty
    	where bo.id = b.boyfriend_id
)

分页查询

应用场景:当我们要显示的数据,一页显示不全,需要分页提交sql请求

语法:

			select 查询列表
			from 表
			【join type  join2
			on 连接条件
			where 筛选条件
			group by 分组字段
			having 分组后的筛选
			order by 排序字段】
			limitoffset,size;
			
			offset要显示条目的起始索引(起始索引从0开始)
			size 要显示的条目个数

特点:

  1. limit语句放在查询语句的最后

  2. 公式

    要显示的页数 page,每页的条目数size

    select 查询列表

    from 表

    limit ,size;

案例1:查询前五条的员工信息

select * from employees limit 0,5;
select * from employees limit 5;
#两条效果相同

案例2:查询第11条到第25条

select * from employees limit 10,15;

案例3:有奖金的员工信息,并且工资较高的前十名显示出来

select * from employees where commission_pct is not null order by salary desc limit 10;

联合查询

union 联合 合并:将多条查询语句的结果合并成一个结果

语法:

查询语句1
union
查询语句2
union
......

应用场景:

当要查询的结果来自于多个表,且多个表没有直接的连接关系,但查询的信息一样时

特点:

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

引入案例:查询部门编号大于90或者是邮箱中包含a的员工信息

select * from employees where email like '%a%' or department_id>90

select * from employees where email like '%a%'
union
select * from employees where email department_id>90

案例:查询中国用户中男性的信息以及外国用户中男性的信息

select id ,cname,csex from t_ca where csex='男'
union
select t_id,tName,tGender from t_ua where tGender='male'

DML语言

数据操作语言:

插入:insert

修改:update

删除:delete

一、插入语句
方式一

语法:

insert into 表名(列名,...) values(,...)
  1. 插入的值的类型要与列的类型一致或兼容

    insert into beauty(id,name,sex,borndate,phone,photo,boyfriend_id)
    values(13,'唐艺昕','女','1990-4-23','1898888888',null,2);
    
  2. 不可以为null的列必须插入值,可以为null的列如何插入值?

    方式一:

    insert into beauty(id,name,sex,borndate,phone,photo,boyfriend_id)
    values(13,'唐艺昕','女','1990-4-23','1898888888',null,2);
    

    方式二:

    insert into beauty(id,name,sex,borndate,phone,boyfriend_id)
    values(13,'唐艺昕','女','1990-4-23','1898888888',2);
    
  3. 列的顺序是否可以调换

    insert into beauty(name,sex,id,phone)
    values('蒋欣','女','16','110')
    可以实现
    
  4. 列数和值的个数必须一致

    insert into beauty(name,sex,id,phone)
    values('关晓彤','女',17,'110')
    
  5. 可以省略列名,默认所有列,而且列的顺序和表中的列的顺序一致

    insert into veauty
    values(18,'张飞','男',null,'119',null,null)
    
方式二:

语法:

insert into 表名
set 列名=,列名=,...
insert into beauty
set id=19,name='刘涛',phone='999'
两种方式大pk

1、方式一支持插入多行,方式二不支持

insert into veauty
values(23,'唐艺昕1','女','1990-4-23','1898888888',null,2),
(24,'唐艺昕2','女','1990-4-23','1898888888',null,2)

2、方式一支持子查询,方式二不支持

insert into beauty(id,name,phone)
select 26,'宋茜','11809866'
insert into beauty(id,name,phone)
select id,boyname,'1234567'
from boys where id<3
二、修改语句
1、修改单表的记录

语法:

update 表名

set 列=新值,列=新值,…

where 筛选条件

案例1:修改beauty表中姓唐的女生的电话为13899888899

update beauty set phone = '13899888899'
where name like '唐%'

案例2:修改boys表中id号为2的名称为张飞,魅力值10

update boys set boyname = '张飞',usercp = 10
where id = 2;
2、修改多表的记录【补充】

92语法:

update 表1 别名,表2 别名

set 列=值,…

where 连接条件

and 筛选条件:

99语法:

update 表1 别名

inner|left|right join 表2 别名

on 连接条件

set 列=值,…

where 筛选条件

案例1:修改张无忌的女朋友的手机号为114

update boys bo
inner join beauty b on bo.id = b.boyfriend_id
set b.phone = '114'
where bo.boyName = '张无忌'

案例2:修改没有男朋友的女生的男朋友的编号都为2号

update boys bo
right join beauty b on bo.id = b.boyfriend_id
set b.boyfriend_id = 2
where b.id is null
三、删除语句
方式一:delete

语法:

1、单表的删除

delete from 表名 where 筛选条件 【limit 条目】

案例1:删除手机号以9结尾的女生信息

delete from beauty where phone like '%9'
2、多表的删除

92语法:

delete 表1的别名,表2的别名 from 表1 别名,表2 别名

where 连接条件 and 筛选条件

99语法:

delete 表1的别名,表2的别名 from 表1 别名

inner|left|right join 表2 别名 on 连接条件

where 筛选条件

案例:删除张无忌的女朋友的信息

delete b 
from beauty b
join boys bo
on b.boyfriend_id = bo.id
where bo.boyName = '张无忌'

案例:黄晓明的信息以及他女朋友的信息

delete b,bo
from beauty b
join boys bo on b.boyfriend_id = bo.id
where bo.boyName = '黄晓明'
方式二:truncate

语法:truncate table 表名

truncate table 不允许加where,只能删除表中全部数据

案例:将魅力值大于100的男生删除

truncate table boys
delete pk truncate
  1. delete 可以加where条件,truncate不能加

  2. truncate删除,效率高一丢丢

  3. 假如要删除的表中有自增长列,如果用delete删除后,在插入数据,自增长列的值从断点开始,

    而truncate删除后,再插入数据,自增长列的值从1开始

  4. truncate删除没有返回值,delete删除有返回值

  5. truncate删除不能回滚,delete删除可以回滚

DDL语言

数据定义语言

库和表的管理

一、库的管理

创建、修改、删除

二、表的管理

创建、修改、删除

创建:create

修改:alter

删除:drop

一、库的管理
1、库的创建

语法:

create database [if not exists] 库名:

案例:创建库Books

create database if not exists books;
if not exists :如果存在则不创建了
2、库的修改

修改库名

rename database books to 新库名:以及废弃的语句,现在没有可以修改库名的语句

可以更改库的字符集

alter database books character set gbk;
3、库的删除
drop database if exists books;
二、表的管理
1、表的创建

语法

create table 表名(

​ 列名 列的类型【(长度)约束】,

​ 列名 列的类型【(长度)约束】,

​ 列名 列的类型【(长度)约束】,

​ …

)

案例:创建表book

create table book(
		id int,#编号
    	bName varchar(20),#图书名
    	price double,#价格
    	authorid int,#作者编号
    	publishDate datetime#出版日期
)

案例:创建表author

create table author(
	id int,
    au_name varchar(20),
	nation varchar(10)
)
2、表的修改

核心语法

alter table 表名 add|drop|modify|change column 列名【列类型,约束】
1、修改列名
alter table book change column publishdate pubDate datetime
2、修改列的类型或约束
alter table book modify column pubdate timestamp;
3、添加新列
alter table author add column annual double;
4、删除列
alter table author drop column annual;
5、修改表名
alter table author rename to book_autor;
三、表的删除
drop table if exists book_author;

通用的写法:

drop database if exists 旧库名;
create database 新库名;

drop table if exists 旧表名;
create table 表名;
四、表的复制
insert into author values
(1,'春上村树','日本'),
(2,'莫言','中国'),
(3,'冯唐','中国');
1、仅仅复制表的结构
create table copy like author;
2、复制表的结构外加数据
create table copy2
select * from author;
3、只复制部分数据
create table copy3
select id,au_name
from author
where nation='中国'
4、仅仅复制某些结构
create table copy4
select id,au_name
from author
where 0;
三、常见的数据类型

原则:所选择的类型越简单越好,能保存数值的类型越小越好

数值型:

​ 整形:

​ 小数:

​ 定点数

​ 浮点数

字符型:

​ 较短的文本:char、varchar

​ 较长的文本:text、blob(较长的二进制数据)

日期型:

一、整形

分类:tinyint、smallint、mediumint、int/integer、bigint

特点:

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

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

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

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

  5. 如何设置无符号和有符号

    create table tab_int(
    	t1 int,
        t2 int unsigned
    )
    
二、小数

分类:

  1. 浮点型

    float(M,D)

    double(M,D)

  2. 定点型

    dec(M,D)

    decimal(M,D)

特点:

  1. M:代表的是整数部位加小数部位

    D:代表小数部位

    如果超过范围,则插入临界值

  2. M和D都可以省略

    如果是定点型,则M默认为10,D默认为0

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

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

三、字符型

分类:

  1. 较短的文本

    char

    varchar

  2. 较长的文本

    text

    blob(较大的二进制)

  3. 其他:

    binary和varbinary用于保存较短的二进制

    enum用于保存枚举

    set用于保存集合

特点:

​ 写法 M的意思 特点 空间的耗费 效率

cahr char(M) 最大的字符数,可以省略,默认为1 固定长度的字符 比较耗费 高

varchar varchar(M) 最大的字符数,不可以省略 可变长度的字符 比较节省 低

四、日期型
  1. date:只保存日期
  2. time:只保存时间
  3. year:只保存年
  4. datetime:保存日期和时间
  5. timestamp:保存日期和时间

特点:

  1. datetime:字节8,范围:1000-9999,不受时区影响
  2. timestamp:字节4,范围:1970-2038,受时区影响
四、常见约束

含义:一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性

分类:六大约束

  1. not null:非空,用于保证该字段的值不能为空,比如姓名、学号等

  2. default:默认,用于保证该字段有默认值,比如性别

  3. primary key:主键,用于保证该字段的值具有唯一性,并且非空比如学号,员工编号等

  4. unioue:唯一,用于保证该字段的值具有唯一性,可以为空,比如座位号

  5. check:检查约束【mysql中不支持】

  6. foreign key:外键,用于限制两个表的关系,用于保证该字段的值必须来自主表的关联列的值

    比如学生表的专业编号,员工表的部门编号,员工表的工种编号

添加约束的时机:

  1. 创建表时
  2. 修改表时

约束的添加分类:

  1. 列级约束:六大约束都可以写,但是外键约束没有效果
  2. 表级约束:除了非空、默认,其他的都支持
create table 表名(
	字段名 字段类型 列级约束
    字段名 字段类型,
    表级约束
)
一、创建表时添加约束
  1. 添加列级约束

    语法:

    直接在字段名和类型后面追加 约束类型即可

    只支持:默认、非空、主键、唯一

    create database students;
    use students;
    
    create table stuinfo(
    		id int primary key,#主键
        	stuName varchar(20) not null,#非空
        	gender char(1) check(gender='男' or gender='女'),#检查
        	seat int unique,#唯一
        	age int default 18,#默认约束
        	majorId int  references major(id)#外键
    )
    CREATE TABLE major(
    	id int primary key,
        majorName varchar(20)
    )
    
  2. 添加表级约束

    语法:在各个字段的最下面

    【constraint 约束名】 约束类型(字段名)

    drop table if exists stuinfo;
    
    create table stuinfo(
    		id int ,
        	stuName varchar(20) ,
        	gender char(1) ,
        	seat int ,
        	age int ,
        	majorId int,
        	
        	constraint pk primary key(id),#主键
        	constraint uq unique(seat),#唯一键
        	constraint ck check(gender='男' or gender='女'),#检查
        	constraint fk_stuinfo_major foreign key(majorid) references major(id)#外键
    )
    
  3. 通用的写法:

    create table if exists stuinfo(
    	id int primary key,
        stuname varchar(20) not null,
        sex char(1),
        age int default 18,
        seat int unique,
        majorid int,
        constraint fk_stuinfo_major foreign key(majorid) references major(id)
    )
    
二、主键和唯一的大对比

主键:保证唯一性,不允许为空,一个表中至多有一个,可以组合但不推荐

唯一:保证唯一性,可以为空,一个表中可以有多个,可以组合但不推荐

三、外键
  1. 要求在从表设置外键关系

  2. 从表的外键列的类型和主表的关联列的类型要求一致或兼容,名称无要求

  3. 主表中的关联列必须是一个key(一般时主键或唯一)

  4. 插入数据时,先插入主表,再插入从表

    删除数据时,先删除从表,再删除主表

四、修改表时添加约束

语法:

添加列级约束:

alter table 表名 modify column 字段名 字段类型 新约束

添加表级约束

alter table 表名 addconstraint 约束名】约束类型(字段名) 【外键的引用】
  1. 添加非空约束

    alter table stuinfo modify column stuname varchar(20) not null
    
  2. 添加默认约束

    alter table stuinfo modify column age int default 18;
    
  3. 添加主键

    #列级约束
    alter table stuinfo modify column id int primary key;
    #表级约束
    alter table stuinfo add  primary key(id)
    
  4. 添加唯一

    #列级约束
    alter table stuinfo modify column seat int unique;
    #表级约束
    alter table strinfo add unique(seat)
    
  5. 添加外键

    alter table stuinfo add foreign key(majorid) references major(id)
    
五、修改表时删除约束
  1. 删除非空约束

    alter table strinfo modify column stuname varchar(20) null;
    
  2. 删除默认约束

    alter table strinfo modify column age int
    
  3. 删除主键

    alter table stuinfo drop primary key;
    
  4. 删除唯一

    alter table stuinfo drop index seat;
    
  5. 删除外键

    alter table stuinfo drop foreign key majorid;
    
五、标识列

又称自增长列

含义:可以不用手动的插入值,系统提供默认的序列值

特点:

  1. 标识列要求是一个key,主键或唯一
  2. 一个表中只可以有一个标识列
  3. 标识列的类型只能是数值型
  4. 标识列可以通过set auto_increment_increment=3设置步长
  5. 可以通过手动插入值设置起始值
一、创建表时设置标识列
create table tab_identity(
	id int primary key auto_increment,
    name varchar(20)
)
二、修改表时设置标识列
alter table tab_identity modify column id int primary key auto_increment;
三、修改表时删除标识列
alter table tab_identity modify column id int  ;

TCL语言

Transaction Control Language 事务控制语言

事务:

一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行

案例:转账

张三丰 1000

郭襄 1000

updateset 张三丰的余额=500 where name = '张三丰'
意外
updateset 郭襄的余额=1500 where name = '郭襄'

show engines查询支持的存储引擎
事务的特性

事务的ACID属性

  1. 原子性(Atomicity)

    原子性是指事物是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生

  2. 一致性(Consistency)

    事务必须使数据库从一个一致性状态变换到另一个一致性状态

  3. 隔离性(lsolation)

    事物的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰

  4. 持久性(Durability)

    持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响

事务的创建
  • 隐式事务:事务没有明显的开启和结束的标记

    比如insert、update、delete语句

  • 显式事务:事务具有明显的开启和结束的标记

    前提:必须先设置自动提交功能为禁用

    set autocommit=0;

    步骤1:开启事务

    set autocommit=0;

    start transaction;可选的

    步骤2:编写事务中的sql语句(select、insert、update、delete)

    语句1;

    语句2;

    步骤3;结束事务

    commit;提交事务

    rollback;回滚事务

  • 演示事务的使用步骤

    #开启事务
    set autocommit=0;
    #编写一组事务的语句
    update account set balance = 500 where username='张无忌'
    update account set balance = 1500 where username='赵敏'
    #结束事务
    commit;
    
  • 对于同时运行多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题:

    1. 脏读:对于两个事务 T1,T2,T1读取了已经被T2更新但还没有被提交的字段之后,若T2回滚,T1读取的内容就是临时且无效的
    2. 不可重复读:对于两个事务T1,T2,T1读取了一个字段,然后T2更新了该字段之后,T1再次读取同一个字段,值就不同了
    3. 幻读:T1从一个表中读取了一个字段,然后T2在该表中插入了一些新的行之后,如果T1再次读取同一个表,就会多几行
  • 数据库事务的隔离性:

    数据库系统必须具有隔离并发运行各个事务的能力,是他们不会相互影响,避免各种并发问题

  • 一个事务与其他事务隔离的程度称为隔离级别,数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性越好,但是并发性越弱

  • 数据库提供的四种事务隔离级别:

    read uncommitted:出现脏读、幻读、不可重复读

    read committed:避免脏读、出现幻读和不可重复读

    repeatable read:避免脏读和不可重复读,出现幻读

    serializable:避免全部

    mysql中默认第三个隔离级别

    oracle中默认第二个隔离级别

    查看级别:select @@tx_isolation

    设置隔离级别:

    set session|global transaction isolation level 隔离级别

  • savepoint 节点名;设置保存点

    演示savepoint的使用

    set autocommit = 0;
    start transaction;
    delete from account where id=25;
    savepoint a;#设置保存点
    delete from account where id=28;
    rollback to a;#回滚到保存点
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值