从零开始:MySQL数据库基础入门笔记——创建、管理与数据操作

1. 数据库基础

1.1 基础概念

  • 数据库:用来存储数据的结构化集合。
  • 表:数据库中的基本存储单位,包含行和列。
  • 字段:表中的列,定义数据的类型。
  • 记录:表中的一行,包含一条数据。
  • 主键 (Primary Key):唯一标识表中每条记录的字段。

1.2 常用数据类型

数据类型作用
INT存储整数
DECIMAL(M,N)有小数点的数,m表示总共有几位数,n表示小数点后面的部分占了几位
FLOAT存储浮点数。
VARCHAR(长度)存储长度可变的字符串,最大为255,可以存储 255 个字符的字符串
CHAR(长度)存储固定长度的字符串,长度不足时会用空格填充。
TEXT用于存储较长的文本数据,没有长度限制,但不能像`CHAR`和`VARCHAR`那样快速排序。
DATE存储日期,格式为`YYYY-MM-DD`。
TIMESTAMP记录时间`YYYY-MM-DD HH: MM: SS`
BLOB全称Binary Large Object用来存放二进制的大型资料,例如图片/影片/档案等

1.3 MySQL代码书写注意事项

  • 标点符号:
    • 分号(;)用于结束一条SQL语句。
    • 逗号(, )用于列出多个列、值或条件
    • 点号(. )用于区分表名和列名,通常在多表查询时使用,因为不同表可能有相同的列名,使用点号来明确表示某列属于哪个表,例如: `employees`.`name`,表示 employees 表中的 name 列。
  • 空格和换行: SQL 语句中空格并不会影响代码的执行,也就是说所有空格都被忽略,但使用空格、在每个主要语句换行等来调整代码的格式,可以提高代码的可读性。
  • 反引号:数据库中的表名、列名等对象最好用反引号圈住(键盘上ESC下面的按钮),防止和MYSQL的关键字冲突。
  • 单引号和双引号:用于包裹字符串值。
  • 大小写:尽管大小写不影响代码执行,但SQL关键字(如 SELECT、INSERT、WHERE 等) 通常使用 大写,以便与表名、列名区分开。
  • 注释:使用 -- 或 #表示单行注释,使用/* ... */表示多行注释
    • 行内注释:-- 之后的文本就是注释,需要注意的是横杠之后有一个空格
    • 整行注释:#通常用于整行注释,使用方法在一行的开始处使用#
    • 多行注释:从/*开始,到*/结束

2. 数据库的创建与管理

2.1 创建数据库

  • 前提:在开始所有的操作之前,我们需要创建一个数据库,也就是存储数据的地方
  • 注意:数据库的名称最好用反引号圈住,防止和MYSQL的关键字冲突
  • 语法:
    CREATE DATABASE 数据库名称;
  • 示例:创建一个名为`company_db`的数据库
    CREATE DATABASE `company_db`;

2.2 显示数据库

  • 查看创建的数据库,显示的数据库中包含MYSQL自带的默认数据库
  • 代码:
    SHOW DATABASES;

2.3 删除数据库

  • 删除某个数据库
  • 语法:
    DROP DATABASE 数据库名称;

2.4 使用数据库

  • 创建完数据库后,需要选择使用哪个数据库,才能在其中进行操作
  • 语法:
    USE 数据库名称;

3. 表的创建与管理

3.1 常见约束条件

  • 前提:在创建表格时经常会对数据添加约束和限制,所以在建表之前先了解常用的约束条件,便于我们更好地理解为什么要使用某些约束和它们的作用
  • 常用约束及其作用:
    约束条件作用
     NOT NULL确保某个列不能有空值(NULL)。
     UNIQUE确保某列的所有值都是唯一的,不能重复。
     PRIMARY KEY每个表格通常都有一个Primary Key(主键),用于唯一标识每一行数据。主键列必须唯一且不能为空(隐含了`NOT NULL`和`UNIQUE`的属性)。
     FOREIGN KEY设置外键约束,确保某个列的值必须在另一个表的特定列中存在。用于建立两张表之间的关联。
     DEFAULT为某个列设置默认值,如果插入时没有指定该列的值,将使用默认值。
     CHECK

    用于限制列的值必须满足一定条件(MySQL 8.0及以上版本支持)。

     AUTO_INCREMENT当给一个字段设置了 AUTO_INCREMENT,在插入新记录时,数据库会自动为该字段分配一个唯一的、递增的整数值,通常与 主键 (Primary Key) 一起使用,注意:一个表中只能有一个字段使用 AUTO_INCREMENT 属性

3.2 创建表

  • 语法:
      CREATE TABLE 表名 (
          列名 数据类型 [约束条件],
          列名 数据类型 [约束条件],
          ...
      );
    
  • 示例:创建一个员工表格`employees`,包含员工ID、姓名和入职日期

    • 约束条件:员工ID唯一为Primary Key(主键),姓名不允许为空置

    • 代码:

      CREATE TABLE `employees` (
          `employee_id` INT PRIMARY KEY,
          `name` VARCHAR(100) NOT NULL,
          `hire_date` DATE
      );
      

3.3 创建父子表

  • 创建父子表需要使用 FOREIGN KEY 关键字定义外键约束,确保子表中的外键列值必须匹配父表中主键列的值。
  • 什么是父子表:
    • 父表是被引用的表,通常包含主键。它的主键被其他表(子表)引用,用来保持数据的一致性和完整性。
    • 子表是引用父表的表,它包含外键,指向父表中的主键。子表依赖父表的存在,通过外键,可以取到父表中的所有信息。
  • 建表顺序:先创建父表(即主键所在的表),并且在建表时或之后添加外键约束,再创建子表。这样能够避免数据插入时由于外键约束导致的错误。
  • 建表时添加外键的语法:
    CREATE TABLE 子表名 (
        列名1 数据类型,
        列名2 数据类型,
        列名3 数据类型,
        ...
        FOREIGN KEY (外键列名) REFERENCES 父表名(父表主键列名)
        [ON DELETE 操作]
        [ON UPDATE 操作]
    );
    
    • ON DELETE 操作 和 ON UPDATE 操作:指定当父表的记录被删除或更新时,子表该如何响应。常见的操作有:

      • CASCADE:父表记录删除或更新时,自动删除或更新子表中引用的记录。

      • SET NULL:父表记录删除或更新时,子表中的外键列设为 NULL(子表列必须允许 NULL)。

      • RESTRICT:拒绝删除或更新父表记录。

  • 示例:创建两个表,一个是 customers 表(父表),另一个是 orders 表(子表),在 orders 表中添加一个外键,引用 customers 表中的 customer_id

    • 创建父表 customers

      CREATE TABLE `customers` (
          `customer_id` INT PRIMARY KEY,
          `customer_name` VARCHAR(255) NOT NULL
      );
      
    • 创建子表 orders 并添加外键

      CREATE TABLE `orders` (
          `order_id` INT PRIMARY KEY,
          `customer_id` INT,
          `order_date` DATE,
          FOREIGN KEY (`customer_id`) REFERENCES `customers`(`customer_id`)
          ON DELETE CASCADE
          ON UPDATE CASCADE
      );
      
    • ON DELETE CASCADE和ON UPDATE CASCADE:表示如果某个 customer_id 在 customers 表中被删除/更新,所有在 orders 表中引用该 customer_id 的记录都会自动删除/更新。

  • 补充:用CONSTRAINT 给外键约束命名,便于后期维护和管理。这样,如果需要修改或删除外键约束时,可以通过约束名称来引用它

    • 语法:

      CONSTRAINT 外键约束名 FOREIGN KEY (外键列名) REFERENCES 父表名(父表主键列名)
    • 示例:在 orders 表中添加一个外键,引用 customers 表中的 customer_id,并把约束命名为fk_customer

      CONSTRAINT `fk_customer` FOREIGN KEY (`customer_id`) REFERENCES `customers`(`customer_id`);

3.4 显示表

  • 语法:
    DESCRIBE 表名; -- 作用:用于显示表的结构
    SHOW COLUMNS FROM 表名; -- 作用:用于显示表的结构
    SHOW CREATE TABLE 表名; -- 作用:显示完整的创建表的 SQL 语句
  • 区别:

    • 前两种方式都是显示表格的结构,用法几乎相同,但" SHOW COLUMNS FROM 表名"更灵活,能够与和 LIKE、WHERE 等条件一起使用来进行更灵活的表结构查询。

      • 注意:显示表的结构,指的是显示有表格的列名、数据类型、是否可以为NULL、是否是主键默认值等基本信息,但不会显示表格中的具体数据(查询表格的数据在第5部分)。

    • 最后一种方式SHOW CREATE TABLE 显示创建该表的 SQL 代码,更适合查看表的创建逻辑显示完整的表定义(包括外键、约束、引擎等)。
  • 示例:

    • 显示表格orders的结构

      DESCRIBE `orders`;

      返回的结果为:

    • 显示表格orders的创建代码

      SHOW CREATE TABLE `orders`;

      返回的结果为:

3.5 修改表

  • 语法:
    ALTER TABLE 表名 [修改操作];

常见修改操作:

3.5.1 添加列

ALTER TABLE 表名 ADD 列名 数据类型;
  • 示例:向`employees`表中添加一个`email`列,数据类型为`VARCHAR(100)`:

    ALTER TABLE `employees` ADD `email` VARCHAR(100);

3.5.2 修改列

  •  MODIFY: 修改列的数据类型,不改变列名。

    ALTER TABLE 表名 MODIFY 列名 新数据类型;
  • 示例:将`employees`表中的`email`列数据类型改为`VARCHAR(150)`:

    ALTER TABLE `employees` MODIFY `email` VARCHAR(150);

  • CHANGE: 同时修改列名和数据类型。

    ALTER TABLE 表格名称 CHANGE 旧列名 新列名 新数据类型;
  • 示例:将`email`列名改为`work_email`,并保持数据类型为`VARCHAR(150)`:

    ALTER TABLE `employees` CHANGE `email` `work_email` VARCHAR(150);

3.5.3 删除列

ALTER TABLE 表名 DROP COLUMN 列名;
  • 示例:删除`employees`表中的`work_email`列:

    ALTER TABLE `employees` DROP COLUMN `work_email`;

3.5.4 重命名表格

ALTER TABLE 旧表格名称 RENAME TO 新表格名称;
  • 示例:将`employees`表重命名为`staff`:

    ALTER TABLE `employees` RENAME TO `staff`;

3.5.5 添加或删除主键

ALTER TABLE 表格名称 ADD PRIMARY KEY (列名); -- 添加主键
ALTER TABLE 表格名称 DROP PRIMARY KEY; -- 删除主键
  • 示例:给`employees`表的`employee_id`列添加主键,然后再删除

    ALTER TABLE `employees` ADD PRIMARY KEY (`employee_id`); -- 添加主键
    ALTER TABLE `employees` DROP PRIMARY KEY; -- 删除主键

3.5.6 添加或删除外键

  • 1. 添加外键

    ALTER TABLE 表格名称 
    ADD CONSTRAINT 外键约束名 FOREIGN KEY (外键列名) REFERENCES 父表名(父表主键列名);
    • 备注:`CONSTRAINT` 用来给外键约束命名,这样如果需要修改或删除外键约束时,可以通过约束名称来引用它

    • 示例:给`employees`表中的`department_id`列添加一个外键,引用`departments`表的`department_id`列:

      ALTER TABLE `employees` ADD CONSTRAINT `fk_department` FOREIGN KEY (`department_id`) REFERENCES `departments`(`department_id`);

  • 2. 删除外键

    • 有外键约束名称:如果创建外键时使用了 CONSTRAINT 来定义约束名称(参考3.3.创建父子表 中的补充内容),可以通过约束名称来删除外键约束

      ALTER TABLE 子表名 DROP CONSTRAINT 约束名称;
      • 示例:在orders 表中定义了外键约束 fk_customer,现在删除这个约束

        ALTER TABLE `orders` DROP CONSTRAINT `fk_customer`;

    • 没有约束名称:如果在创建外键时没有指定 CONSTRAINT 名称,MySQL 会自动为外键生成一个内部的名称。要删除这样的外键约束,必须使用 DROP FOREIGN KEY,通过外键的自动生成的名称进行删除

      ALTER TABLE 子表名 DROP FOREIGN KEY 外键名称;
      • 示例:假设在 orders 表中定义了一个没有命名的外键 customer_id,也就是MySQL 自动生成的外键名称,现在删除这个外键
        ALTER TABLE `orders` DROP FOREIGN KEY `customer_id`;
      • 备注:查询自动生成的外键名称:使用" SHOW CREATE TABLE 表名; "系统生成的名称也会在 CONSTRAINT 后显示

3.6 删除表

  • 语法:
    DROP TABLE 表名;
  • 示例:删除一个员工表格`employees`

    DROP TABLE `employees`;

4. 数据操作

4.1 插入数据

4.1.1 插入单条记录

  • 语法:
    INSERT INTO 表格名称 (列1, 列2, 列3, ...) VALUES (值1, 值2, 值3, ...);
  • 语法含义:向指定的表中插入一条记录,列出的列名对应需要插入的值。如果列名省略则表示按照表格中从左到右的排序插入值。

  • 示例:向`employees`表中插入一条记录,`employee_id`为`1`,`name`为`Alice`,`hire_date`为`20230903`

    INSERT INTO `employees` (`employee_id`, `name`, `hire_date`) VALUES (1, 'Alice', '20230903');

4.1.2 插入多条记录

  • 语法:
    INSERT INTO 表格名称 (列1, 列2, 列3, ...) VALUES (值1, 值2, 值3, ...), (值1, 值2, 值3, ...), ...;
  • 语法含义:一次插入多条记录,通过在`VALUES`后面提供多个值列表来实现。
  • 示例:一次性插入两条记录,分别是`Charlie`和`Diana`的雇佣信息
    INSERT INTO `employees` (`employee_id`, `name`, `hire_date`) 
    VALUES (2, 'Charlie', '20210510'), 
           (3, 'Diana', '20200722');
    

4.1.3 插入部分列

  • 语法:
    INSERT INTO 表格名称 (列1, 列2) VALUES (值1, 值2);
  • 语法含义:只插入部分列的值,未指定的列将使用默认值或`NULL`。
  • 示例:`Bob`的`employee_id`没有被插入,MySQL会自动给这个字段分配默认值(如`AUTO_INCREMENT`列)
    INSERT INTO `employees` (`name`, `hire_date`) VALUES ('Bob', '20220815');

4.1.4 从另一个表中插入数据

  • 语法:
    INSERT INTO 目标表格 (列1, 列2, ...) SELECT 列1, 列2, ... FROM 源表格 WHERE 条件;
  • 语法含义:从一个表中选择数据,并将这些数据插入到另一个表中。常用于将查询结果插入到目标表。
  • 示例:从`employees`表中选择`hire_date`大于`20210101`的员工,并将其插入到`employees_backup`表中
    INSERT INTO `employees_backup` (`employee_id`, `name`, `hire_date`)
    SELECT `employee_id`, `name`, `hire_date` FROM employees WHERE hire_date > '20210101';

4.1.5 插入或更新

  • 语法:

    INSERT INTO 表格名称 (列1, 列2, ...) VALUES (值1, 值2, ...) 
    ON DUPLICATE KEY UPDATE 列1=新值1, 列2=新值2, ...;
  • 语法含义:如果插入的记录导致主键或唯一键冲突,则进行更新而不是插入

  • 示例:如果`employee_id`为`1`的记录已存在,这条语句会更新该记录的`name`和`hire_date`为新的值

    INSERT INTO `employees` (`employee_id`, `name`, `hire_date`) 
    VALUES (1, 'Alice', '20230903') 
    ON DUPLICATE KEY UPDATE `name`='Alice Updated', `hire_date`='20230904';

4.1.6 插入忽略

  • 语法:

    INSERT IGNORE INTO 表格名称 (列1, 列2, ...) VALUES (值1, 值2, ...);
  • 语法含义:当插入的记录导致主键或唯一键冲突时,忽略这条记录而不报错。

  • 示例:如果`employee_id`为`1`的记录已存在,MySQL会忽略这次插入操作,不会插入新记录也不会抛出错误

    INSERT IGNORE INTO `employees` (`employee_id`, `name`, `hire_date`) 
    VALUES (1, 'Alice', '20230903');

4.2 更新数据

关闭 MySQL 的“安全更新模式”

  • 代码临时关闭:
    SET SQL_SAFE_UPDATES = 0;
  • 手动关闭:在 MySQL Workbench 中找到Edit-> Preferences -> SQL Editor,取消勾选 Safe Updates,重启 MySQL Workbench。

  • 含义:在 MySQL 中,SQL_SAFE_UPDATES 是一个安全选项,目的是防止用户在更新或删除大量数据时,无意中执行不带 WHERE 子句的 SQL 语句,进而修改或删除整个表的数据。

4.2.1 更新单列

  • 语法:
    UPDATE 表名 SET 列名 = 新值 WHERE 条件;
  • 语法含义:根据条件更新表中某一列的值。

4.2.2 更新多列​​​​​

  • 语法:
    UPDATE 表名 SET 列名1 = 新值1, 列名2 = 新值2 WHERE 条件;
  • 语法含义:根据条件同时更新表中的多列数据
  • 示例:将 employee_id 为 1 的员工的 name 更新为 'Alice Johnson',hire_date 更新为 '20231001'
    UPDATE `employees` 
    SET `name` = 'Alice Johnson', `hire_date` = '20231001' 
    WHERE `employee_id` = 1;

4.2.3 使用 AND 或 OR 组合多个条件更新

  • 语法:
    UPDATE 表名 SET 列名 = 新值 WHERE 条件1 AND/OR 条件2;
  • 示例:同时满足 employee_id 为 2 且 name 为 'Charlie' 的记录,其 hire_date 被更新为 '20231001'
    UPDATE `employees` 
    SET `hire_date` = '20231001' 
    WHERE `employee_id` = 2 AND `name` = 'Charlie';

4.2.4 使用 CASE 语句更新

  • 语法:
    UPDATE 表名 SET 列名 = CASE
        WHEN 条件1 THEN 值1
        WHEN 条件2 THEN 值2
        ELSE 默认值
    END
    WHERE 条件;
    
  • 语法含义:`CASE` 语句允许根据多个条件选择更新不同的值。`WHERE` 条件用于定义更新的范围,仅更新符合该条件的行。
  • 示例:根据不同的 employee_id 更新 hire_date,如果是 employee_id 为 1 则更新为 '20241001',如果为 2 则更新为 '20240101',其他情况下保持原始值 '20200722'
    UPDATE `employees`
    SET `hire_date` = CASE
        WHEN `employee_id` = 1 THEN '20241001'
        WHEN `employee_id` = 2 THEN '20240101'
        ELSE '20200722'
    END
    WHERE `employee_id` IN (1, 2, 3);

4.2.5 没有 WHERE 子句的全部更新

  • 语法:
    UPDATE 表名 SET 列名 = 新值;
  • 语法含义:不使用 `WHERE` 子句时,更新表中所有记录的值。要谨慎使用,因为这会对表中的每一行数据进行更改。
  • 示例:更新 employees 表中所有员工的 hire_date 为 '20240101'
    UPDATE `employees` SET `hire_date` = '20240101';

4.3 删除数据

4.3.1 删除单条记录

  • 语法:
    DELETE FROM 表格名称 WHERE 条件;
  • 含义:根据指定条件删除符合条件的单条记录。

  • 示例:

    DELETE FROM `employees` WHERE `employee_id` = 1;

4.3.2 删除多条记录

  • 语法:
    DELETE FROM 表格名称 WHERE 条件;
  • 含义:同样根据条件删除多条符合条件的记录。

  • 示例:删除 `employee_id` 为 2 或 3 的员工记录

    DELETE FROM `employees` WHERE `employee_id` IN (2, 3);

4.3.3 使用 AND 或 OR 基于多个条件删除数据

  • 语法:
    DELETE FROM 表名 WHERE 条件1 AND 条件2;
    DELETE FROM 表名 WHERE 条件1 OR 条件2;
  • 含义:可以使用 AND 或 OR 组合多个条件来删除数据。

  • 示例:删除所有 `hire_date` 在 2022 年 1 月 1 日之前或者 `name` 为 `Charlie` 的员工记录

    DELETE FROM `employees` WHERE `hire_date` < '2022-01-01' OR `name` = 'Charlie';

4.3.4 删除所有记录(小心使用)

  • 语法:
    DELETE FROM 表名;
  • 含义:删除表中的所有记录,但表结构依然保留。

4.3.5 使用 TRUNCATE 语句删除所有记录(更快但不可恢复)

  • 语法:
    TRUNCATE TABLE 表名;
  • 含义:快速删除表中所有记录,重置表的自增计数(如果有),不可恢复。

  • 备注:自增计数是指在表中某个字段(通常是主键)每插入一条新记录时,自动为其生成一个唯一的数字。

5. 查询数据

注意区分:`SELECT`语句返回的结果显示的是表格中的具体数据(和excel类似),而`DESCRIBE`显示的是表格的结构,包括列名、数据类型、是否可以为NULL等信息。

5.1 查询所有记录

  • 语法:
    SELECT * FROM table_name;
  • 含义:使用 SELECT * 查询表中的所有记录
  • 示例:
    -- 查询所有员工记录
    SELECT * FROM `employees`;
    

5.2  查询特定列

  • 语法:
    SELECT column1, column2 FROM table_name;
  • 含义:只查询选择的特定列
  • 示例:
    -- 查询员工的姓名和入职日期
    SELECT `name`, `hire_date` FROM `employees`;

5.3 使用 WHERE 进行条件查询

  • 语法:
    SELECT column1, column2 FROM table_name WHERE condition;
  • 含义:根据特定条件筛选记录。
  • 示例:
    -- 查询入职日期在2020年之后的员工
    SELECT * FROM `employees` WHERE `hire_date` > '2020-01-01';

5.4 使用 ORDER BY 排序

  • 语法:
    SELECT column1, column2 FROM table_name
    ORDER BY column1 [ASC|DESC], column2 [ASC|DESC];
  • 含义:使用 ORDER BY 子句对查询结果进行排序,升序(ASC)或降序(DESC),默认为升序,可以多列排序
  • 示例:
    -- 按部门ID升序和入职日期降序排序查询所有员工
    SELECT * FROM `employees` ORDER BY `department_id` ASC, `hire_date` DESC;

5.5 使用 LIMIT 限制返回的记录数

  • 语法:
    SELECT column1, column2 FROM table_name
    LIMIT number;
  • 含义:限制查询结果的条数
  • 示例:
    -- 查询前两名员工
    SELECT * FROM `employees` LIMIT 2;

5.6 返回唯一值

  • 语法:
    SELECT DISTINCT column1 FROM table_name;
  • 含义:对表格中的某一列去重后返回唯一值
  • 示例:
    -- 查询 employees 表中所有不同的职位
    SELECT DISTINCT `position` FROM `employees`;

5.7 使用 JOIN 进行表连接

  • 含义:连接多个表以获取更多信息
  • 连接模式:
    • INNER JOIN:返回两个表中匹配的记录,也可以省略INNER
    • LEFT JOIN:返回左表中的所有记录,以及右表中匹配的记录
    • RIGHT JOIN:返回右表中的所有记录,以及左表中匹配的记录
    • 如何分辨左表和右表:并排写代码时在JOIN的左边就是左边的表格
    • LEFT JOIN 和 RIGHT JOIN 返回的记录中如果有未匹配的部分列会显示为 NULL
  • 示例:假设我们有一张员工表,包含员工信息,一张部门表,包含部门信息
    员工表
      
    部门表
  • 创建表格:
    -- 删除原来的部门表和员工表
    DROP TABLE `employees`,`departments`;
    
    
    -- 创建部门表
    CREATE TABLE `departments` (
        `department_id` INT AUTO_INCREMENT PRIMARY KEY,
        `department_name` VARCHAR(100)
    );
    
    -- 插入示例数据
    INSERT INTO `departments` (`department_name`) VALUES
    ('HR'),
    ('IT'),
    ('Sales');
    
    -- 创建员工表并添加部门列
    CREATE TABLE `employees` (
        `employee_id` INT AUTO_INCREMENT PRIMARY KEY,
        `name` VARCHAR(100),
        `hire_date` DATE,
        `department_id` INT,  -- 添加部门ID列
        FOREIGN KEY (`department_id`) REFERENCES `departments`(`department_id`)
    );
    
    -- 插入示例数据
    INSERT INTO `employees` (`name`, `hire_date`, `department_id`) VALUES
    ('Alice', '2023-09-03', 1),
    ('Bob', '2021-05-10', 2),
    ('Charlie', '2020-07-22', 1);

  • INNER JOIN 连接
    -- 查询员工姓名和他们所属的部门(INNER JOIN)
    SELECT 
        `employees`.`name`, 
        `departments`.`department_name`
    FROM 
        `employees`
    INNER JOIN 
        `departments` ON `employees`.`department_id` = `departments`.`department_id`;
    • 解释:查询员工的姓名和对应的部门名称,使用 employees 表和 departments 表的 department_id 进行匹配,返回的是两个表中匹配的结果

INNER JOIN 返回结果
  • LEFT JOIN 连接

    -- 查询所有员工及其部门名称(LEFT JOIN)
    SELECT 
        `employees`.`name`, 
        `departments`.`department_name`
    FROM 
        `employees`
    LEFT JOIN 
        `departments` ON `employees`.`department_id` = `departments`.`department_id`;
    • 解释:返回左表 employees 中的所有员工的 name 和右表 departments 中与之对应的部门名称

      LEFT JOIN 返回结果
  • RIGHT JOIN 连接

    -- 查询所有部门及其员工姓名(RIGHT JOIN)
    SELECT 
        `employees`.`name`, 
        `departments`.`department_name`
    FROM 
        `employees`
    RIGHT JOIN 
        `departments` ON `employees`.`department_id` = `departments`.`department_id`;

    • 解释:返回右表 departments 中的所有的 department_name 和左表 employees 中与之对应的员工姓名,未匹配到员工姓名的列会显示为 NULL

    RIGHT JOIN 返回结果

5.8 分组查询:使用 GROUP BY 和聚合函数

  • 说明:GROUP BY 用于将具有相同值的行分组,通常与聚合函数(如 COUNT()、SUM()、AVG() 等)一起使用,对分组后的数据进行汇总计算。
  • 语法:
    SELECT 列名, 聚合函数(列名)
    FROM 表
    WHERE 条件
    GROUP BY 列名;
    
  • 注意:上面语法中的 WHERE 是在数据分组之前进行筛选的,因此只能作用于表中的原始数据,而不能作用于聚合后的结果。想要筛选聚合结果,我们使用的是 HAVING 子句,在下个部分有介绍。
  • 常用聚合函数:
    • COUNT(列名): 统计行数
    • SUM(列名): 计算总和
    • AVG(列名): 计算平均值
    • MAX(列名): 计算最大值
    • MIN(列名): 计算最小值
  • 示例:向 employees 表中插入一列 salary
    -- salary 类型为 DECIMAL(10, 2),表示最多10位数字,保留2位小数,默认值为 0
    ALTER TABLE `employees`
    ADD COLUMN `salary` DECIMAL(10, 2) DEFAULT 0;
    
    -- 更新新添加的 salary 列数据
    UPDATE `employees`
    SET `salary` = CASE
        WHEN `employee_id` = 1 THEN 5000
        WHEN `employee_id` = 2 THEN 6000
        ELSE 5500
    END;
    更新后的 employees 表
  • -- 计算每个部门的员工总数和总工资
    SELECT `department_id`, COUNT(`employee_id`) AS `employee_count`, SUM(`salary`) AS `total_salary`
    FROM `employees`
    GROUP BY `department_id`;
分类汇总后显示的结果

5.9 使用 HAVING 子句筛选分组后结果

  • 说明:HAVING 子句用于筛选 GROUP BY 之后的数据,常与聚合函数一起使用,类似于 WHERE 子句,但 WHERE 不能用于聚合函数,而 HAVING 可以。
  • 语法:
    SELECT 列名, 聚合函数(列名)
    FROM 表
    GROUP BY 列名
    HAVING 聚合函数(列名) 条件;
    
  • 示例:

    -- 查询工资总和超过 10000 的部门
    SELECT `department_id`, SUM(`salary`) AS `total_salary`
    FROM `employees`
    GROUP BY `department_id`
    HAVING SUM(`salary`) > 10000;
    筛选结果

5.10 子查询

  • 语法:

    SELECT 列名
    FROM 表
    WHERE 列名 运算符 (SELECT 列名 FROM 表 WHERE 条件);
  • 含义:子查询,将一个查询嵌套在另一个查询中(放在括号里面),可以用于复杂的查询场景

  • 示例:

    -- 查询工资高于 employees 表中平均工资的员工
    SELECT `name`, `salary`
    FROM `employees`
    WHERE `salary` > (SELECT AVG(`salary`) FROM `employees`);
    查询结果

5.11 模糊查询

  • 语法:
    SELECT 列名
    FROM 表名
    WHERE 列名 LIKE '模式';
  • 含义:模糊查询用于查找符合某个模式的记录,通常使用 LIKE 关键字。可以配合通配符 _ 和 % 来完成查询:
    • _:匹配单个字符。
    • %:匹配零个或多个字符。
  • 示例:
    -- 查询所有名字以 'A' 开头的员工
    SELECT `name`
    FROM `employees`
    WHERE `name` LIKE 'A%';
    
    -- 查询所有名字的第二个字符为 'l' 的员工
    SELECT `name`
    FROM `employees`
    WHERE `name` LIKE '_l%';

5.12 AS 的使用

  • 说明:`AS` 关键字用于为表或列设置别名。使用别名可以让查询更加简洁或易于理解,尤其是在连接多个表时。
  • 语法:
    SELECT 列名 AS 别名
    FROM 表名 AS 表别名;
  • 含义:

    • 列别名:为查询结果中的列设置别名,列别名会显示在查询结果的列名中。

    • 表别名:为表设置一个临时名称,通常在涉及多表查询时使用,可以简化查询语句。

    • 可选的关键字:`AS` 是可选的,也就是说可以直接写别名,而不使用 `AS`。

  • 示例:
    -- 查询员工姓名和他们所属的部门
    SELECT e.`name`, d.`department_name`
    FROM `employees` AS e
    JOIN `departments` AS d ON e.`department_id` = d.`department_id`;
    
        
    -- 等同于
    SELECT e.`name`, d.`department_name`
    FROM `employees`  e
    JOIN `departments`  d ON e.`department_id` = d.`department_id`;

6. 常见错误处理

6.1 Error 1062: Duplicate entry for key

  • 问题:插入或更新操作时,试图在唯一索引或主键列中插入重复值。
  • 解决方法:确保插入的数据在主键或唯一列中没有重复。

6.2 Error 1451: Cannot delete or update a parent row

  • 问题:试图删除父表中的记录,但该记录在子表中作为外键被引用。
  • 解决方法:可以使用 `ON DELETE CASCADE` 来级联删除子表中的相关记录,或先手动删除子表中的外键记录。

6.3 Error 1175: Safe mode update error

  • 问题:在 MySQL Workbench 的安全更新模式下,试图更新或删除没有使用主键或唯一索引的 `WHERE` 子句的数据。
  •  解决方法:可以在 SQL Editor 中禁用安全更新模式,或使用 `SET SQL_SAFE_UPDATES = 0;`。

6.4 Error Code: 1046. No database selected

  • 问题:这个错误表示在执行 SQL 语句时,没有选择任何默认的数据库。
  •  解决方法:
    • 手动选择数据库:在运行 SQL 语句之前,必须使用 USE 语句来明确指定要操作的数据库。例如:
      USE `your_database_name`;
      
    • 通过 MySQL Workbench 界面选择数据库:如果你使用的是 MySQL Workbench,可以在左侧的 SCHEMAS 列表中双击目标数据库名,这样会自动将该数据库设为默认数据库。

    • 在 SQL 语句中明确指定数据库:你也可以在 SQL 查询语句中指定数据库名称。例如:

      SELECT * FROM `your_database_name`.`your_table_name`;

6.5 Could not acquire management access for administration

  • 问题:没有足够的权限访问 MySQL 服务器进行管理操作,或 MySQL 服务未启动
  • 解决方法:
    • 确保 MySQL 服务正在运行:使用 `Win + R`,输入 `services.msc`,打开服务管理器,找到 `MySQL` 服务,右键选择启动。
    • 检查用户权限:确保你使用的数据库用户有足够的权限来执行管理操作。使用 GRANT ALL PRIVILEGES 语句可以赋予用户更多权限。
      GRANT ALL PRIVILEGES ON *.* TO 'username'@'localhost';
      FLUSH PRIVILEGES;
      • 这个语句的作用是,允许 'username' 用户在本地服务器(localhost)上拥有对所有数据库的所有权限,之后使用 FLUSH PRIVILEGES; 刷新权限表,使更改立即生效

    • 检查 MySQL 配置文件:如果是服务器问题,检查 MySQL 配置文件 my.cnf 或 my.ini 是否禁用了远程管理功能,或查看是否存在相关的管理访问限制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值