1.多表查询

1.1、内连接

  • 隐式内链接

    select 字段列表 from 表1,表2 where 条件...
    
  • 练习

-- 内连接
# 1.查询员工的姓名,及所属的部门名称(隐式内连接实现)
select tb_emp.name,tb_dept.name from tb_emp,tb_dept where tb_emp.dept_id = tb_dept.id;
  • 显式内连接

    select 字段列表 from 表1 [inner] join 表2 on 连接条件...
    
  • 练习

# 2.查询员工姓名,及所属的部门名称(显示内连接实现)
select e.name,d.name from tb_emp e inner join tb_dept d on e.dept_id = d.id;

1.2、外连接

  • 左外连接

    select 字段列表 from 表1 left [outer] join 表2 on 连接条件...
    
  • 练习

#1.查询员工表所有员工的姓名和对应的部门名称(左连接)
select e.name,d.name from tb_emp e left join tb_dept d on e.dept_id = d.id;
  • 右外连接

    select 字段列表 from 表1 right [outer] join 表2 on 连接条件...
    
  • 练习

    #2.查询部门表所有部门的名称和对应的员工名称(右连接)
    select e.name,d.name from tb_emp e right join tb_dept d on e.dept_id = d.id;
    

1.3、子查询

  • 概述

    • 介绍:SQL语句中嵌套select语句,称为嵌套查询,又称子查询
    • 形式:select * from t1 where column1 = (select column1 from t2);
    • 子查询外部的语句可以是insert/update/delete/select的任何一个,常见的为select
  • 分类

    • 标量子查询
      • 子查询返回的结果是单个值(数字、字符串、日期等)
    -- 标量子查询
    #1.查询“教研部”的所有员工信息
    select * from tb_emp where dept_id = (select id from tb_dept where name = '教研部');
    #2.查询在“房东白”入职之后的员工信息
    select * from tb_emp where entrydate > (select a.entrydate from tb_emp a where name = '方东白');
    
    • 列子查询
      • 返回的结果是一列(可以是多行)
    -- 列子查询
    # 查询“教研部”和“咨询部”所有的员工信息
    select * from tb_emp where dept_id in (select id from tb_dept where name in ('教研部','咨询部'));
    
    • 行子查询
      • 返回的结果是一行(可以是多列)
    -- 行子查询
    # 查询与 “韦一笑”的入职日期及职位都相同的员工信息
    select * from tb_emp where entrydate = (select entrydate from tb_emp where name = '韦一笑')
        and job = (select job from tb_emp where name = '韦一笑');
    #优化
    select * from tb_emp where (entrydate,job) = (select entrydate,job from tb_emp where name = '韦一笑');
    
    • 表子查询
      • 返回的结果是多行多列,常作为临时表
    # 查询入职日期是'2006-01-01'之后的员工信息,及其部门名称
    select e.*,d.name from (select * from tb_emp where entrydate > '2006-01-01')
        e join tb_dept d on e.dept_id = d.id;
    

1.4、案例

  • 导入数据表

image-20230810233707910.png

image-20230810233714330.png

-- 1. 查询价格低于 10元 的菜品的名称 、价格 及其 菜品的分类名称 .
select d.name, d.price, c.name
from dish d,
     category c
where d.category_id = c.id
  and d.price < 10;

-- 2. 查询所有价格在 10元(含)到50元(含)之间 且 状态为'起售'的菜品名称、价格 及其 菜品的分类名称 (即使菜品没有分类 , 也需要将菜品查询出来).
select d.name, d.price, c.name
from dish d
         left join category c on d.category_id = c.id
where d.price between 10 and 50
  and d.status = 1;

-- 3. 查询每个分类下最贵的菜品, 展示出分类的名称、最贵的菜品的价格 .
select max(d.price),c.name from dish d join category c on d.category_id = c.id group by c.id;

-- 4. 查询各个分类下 状态为 '起售' , 并且 该分类下菜品总数量大于等于3 的 分类名称 .
select c.name,count(*) from dish d,category c where d.category_id = c.id and d.status = 1 group by c.id having count(*)>=3;

-- 5. 查询出 "商务套餐A" 中包含了哪些菜品 (展示出套餐名称、价格, 包含的菜品名称、价格、份数).
select s.name,s.price,d.name,d.price,sd.copies from setmeal s right join setmeal_dish sd
    on s.id = sd.setmeal_id
    join dish d on d.id = sd.dish_id
where s.name = '商务套餐A';

select s.name,s.price,d.name,d.price,sd.copies from setmeal s,setmeal_dish sd,dish d where s.id = sd.setmeal_id and d.id = sd.dish_id and s.name='商务套餐A'
-- 6. 查询出低于菜品平均价格的菜品信息 (展示出菜品名称、菜品价格).
-- 总价格 select sum(price) from dish
-- 总数  select count(*) from dish
select * from dish where price < (select avg(price) from dish);

2.事务

  • 场景

    • 删除某个部门,该部门下的员工也需要删除
  • 操作

    delete from tb_dept where id = 1;
    delete from tb_emp where dept_id = 1;
    
  • 问题

    • 如果删除部门成功了,而删除该部门的员工时失败, 就造成了数据的不一致

2.1、介绍&操作

  • 概述
    • 事务是一组操作的集合,它是一个不可分割的工作单位。事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败

注意事项:默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐式的提交事务

  • 事务控制

    • 开启事务
    start transaction / begin;
    
    • 提交事务
    commit;
    
    • 回滚事务
    rollback;
    

2.2、四大特性

  • ACID
    • 原子性(Atomicity):事务是不可分割的最小单元,要么全部成功,要么全部失败
    • 一致性(consistency):事务完成时,必须使所有的数据都保持一致状态
    • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行
    • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据改变就是永久的

3.索引

3.1、介绍

  • 索引(index)是帮助数据高效获取数据数据结构

image-20230810233727291.png

  • 优点
    • 提高数据查询的效率、降低数据库的IO成本
    • 通过索引列对数据进行排序、降低数据排序的成本,降低CPU消耗
  • 缺点
    • 索引会占用存储空间
    • 索引大大提高了查询效率,同时却也降低了insert update delete的效率

3.2、结构

MySQL数据库支持的索引结构有很多,例如:Hash索引、B+Tree索引、Full-Text索引等。我们平常所说的索引,如果没有特别指定,都是默认为B+Tree结构组织的索引

  • B+Tree(多路平衡搜索树)
    • 每一个节点,可以存储多个key(有n个key,就有n个指针)
    • 所有的数据都存储在叶子节点,非叶子节点仅用于索引数据
    • 叶子节点形成了一颗双向链表,便于数据的排序及区间范围查询

image-20230810233737628.png

3.3、语法

  • 创建索引
create [unique] index 索引名 on 表名(字段名);
  • 查看索引
show index from 表名;
  • 删除索引
drop index 索引名 on 表名;
  • 【注意事项】
    • 主键字段,在建表时,会自动创建主键索引
    • 添加唯一约束时,数据库实际上会添加唯一索引

4.MyBatis入门

  • 概述
    • MyBatis是一款优秀的持久层 框架,用于简化JDBC的开发
    • MyBatis本事Apache的一个开源项目iBatis,2010念这个项目有apache迁移到了google code,并且改名为MyBatis。2013.11迁移到了Github
    • 官网:https://mybatis.org/mybatis-3/zh/index.html

4.1、快速入门

使用Mybatis查询所有用户数据

  • 步骤

    • 创建springboot工程、数据库表user、实体类User

image-20230810233748154.png

  • 引入MyBatis相关依赖,配置MyBatis

image-20230810233755670.png

image-20230810233803012.png

  • 编写SQL语句(注解/XML)

    @Mapper  //在运行时,会自动生成该接口的实现类对象,并且将该对象交给SpringIOC管理
    public interface UserDao {
      @Select("select * from user")
      List<User> getUsers();
    }
    
  • 单元测试

    @SpringBootTest
    class SpringbootProject01ApplicationTests {
      @Autowired
      private UserDao userDao;
      @Test
      public void test(){
          System.out.println(userDao.getUsers().toString());
      }
    }
    
  • 配置SQL提示

    • 默认在MyBatis中编写SQL语句是不识别的,做如下配置:

image-20230810233810318.png

image-20230810233828026.png

image-20230810233840407.png

【可能出现】:

image-20230810233846512.png

  • 产生原因:IDEA和数据库没有建立连接,没识别表信息
  • 解决方法:在当前项目下连接数据库即可

4.2、JDBC介绍

  • JDBC(Java DataBase Connectivity)
    • 使用Java语言操作关系型数据库的一套API
  • 本质
    • sun公司定义的一套操作所有关系型数据库的规范,即接口
    • 各个数据库厂商去实现这套接口,提供数据库驱动jar包
    • 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的是实现类
  • JDBC原始代码
@Test
public void testJdbc() throws Exception {
    //1. 注册驱动
    Class.forName("com.mysql.cj.jdbc.Driver");

    //2. 获取连接对象
    String url = "jdbc:mysql://localhost:3306/mybatis";
    String username = "root";
    String password = "1234";
    Connection connection = DriverManager.getConnection(url, username, password);

    //3. 获取执行SQL的对象Statement,执行SQL,返回结果
    String sql = "select * from user";
    Statement statement = connection.createStatement();
    ResultSet resultSet = statement.executeQuery(sql);

    //4. 封装结果数据
    List<User> userList = new ArrayList<>();
    while (resultSet.next()){
        int id = resultSet.getInt("id");
        String name = resultSet.getString("name");
        short age = resultSet.getShort("age");
        short gender = resultSet.getShort("gender");
        String phone = resultSet.getString("phone");

        User user = new User(id,name,age,gender,phone);
        userList.add(user);
    }

    //5. 释放资源
    statement.close();
    connection.close();
}

4.3、数据库连接池

  • 概述
    • 数据库连接池是个容器,负责分配、管理数据库连接(Connection)
    • 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
    • 释放空间时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏
  • 优势

    • 资源重用
    • 提升系统响应速度
    • 避免数据库连接遗漏
  • 标准接口:DataSource

    • 官方(sun)提供的数据库连接池接口,由第三方组织实现此接口
    • 功能:获取连接 Connection getConnection() throws SQLException;
  • 常见产品

image-20230810233858803.png

  • 切换Druid数据库连接池
    • 添加durid的依赖即可

4.4、lombok

  • 问题分析
    • 实体类内含有 有参、无参构造方法,getter、setter,toString、Hashcode、equals等方法,代码太过臃肿
  • Lombok是一个实用的Java类库,能通过注解的形式自动生成构造器,equals、toString等方法,并可以自动化生成日志变量,简化Java开发,提高效率

image-20230810233906802.png

【注意事项】:Lombok会在编译时,自动生成对应的java代码,我们使用lombok时,还需要安装lombok的插件(一般版本靠前的idea自带)

results matching ""

    No results matching ""