Mysql--基础篇--SQL(DDL,DML,窗口函数,CET,视图,存储过程,触发器等)

news2025/1/8 15:19:11

SQL(Structured Query Language,结构化查询语言)是用于管理和操作关系型数据库的标准语言。它允许用户定义、查询、更新和管理数据库中的数据。SQL是一种声明性语言,用户只需要指定想要执行的操作,而不需要详细说明如何实现这些操作。SQL被广泛应用于各种数据库系统,如MySQL、PostgreSQL、Oracle、SQL Server等。

为了更全面地理解SQL,我们可以将其分为以下几个主要部分:

  • 数据定义语言(DDL)
  • 数据操作语言(DML)
  • 数据查询语言(DQL)
  • 数据控制语言(DCL)
  • 事务控制语言(TCL)

1、数据定义语言(DDL)

DDL用于定义和管理数据库的结构,包括创建、修改和删除数据库对象(如表、索引、视图等)。

常见的 DDL 操作包括:

  • CREATE:创建数据库对象。
  • ALTER:修改现有数据库对象的结构。
  • DROP:删除数据库对象。
  • TRUNCATE:清空表中的所有数据,但保留表结构。
  • RENAME:重命名数据库对象。

使用示例:

  • 创建数据库:
 CREATE DATABASE mydatabase;
  • 创建表:
  CREATE TABLE employees (
      id INT PRIMARY KEY,
      name VARCHAR(100),
      age INT,
      department VARCHAR(50)
  );
  • 修改表结构:
  ALTER TABLE employees ADD COLUMN salary DECIMAL(10, 2);
  • 删除表:
  DROP TABLE employees;
  • 清空表数据:
  TRUNCATE TABLE employees;
  • 重命名表:
  RENAME TABLE old_table_name TO new_table_name;

2、数据操作语言(DML)

DML用于插入、更新和删除数据库中的数据。

常见的DML操作包括:

  • INSERT:向表中插入新数据。
  • UPDATE:更新表中的现有数据。
  • DELETE:从表中删除数据。

使用示例:

  • 插入数据:
  INSERT INTO employees (id, name, age, department) VALUES (1, 'Alice', 30, 'HR');
  • 批量插入数据:
  INSERT INTO employees (id, name, age, department) VALUES 
  (2, 'Bob', 28, 'Engineering'),
  (3, 'Charlie', 35, 'Sales');
  • 更新数据:
  UPDATE employees SET salary = 60000 WHERE id = 1;
  • 删除数据:
  DELETE FROM employees WHERE id = 2;
  • 删除所有数据:
  DELETE FROM employees;

3、数据查询语言(DQL)

DQL用于从数据库中检索数据,最常见的DQL语句是SELECT。通过SELECT语句,用户可以查询表中的数据,并使用各种条件、排序、分组等功能来获取所需的结果。

使用示例:

  • 基本查询:
  SELECT * FROM employees;
  • 选择特定列:
  SELECT name, age FROM employees;
  • 带条件的查询:
  SELECT * FROM employees WHERE department = 'HR';
  • 使用AND/OR组合条件:
  SELECT * FROM employees WHERE department = 'HR' AND age > 30;
  • 使用IN进行多值匹配:
  SELECT * FROM employees WHERE department IN ('HR', 'Sales');
  • 使用LIKE进行模糊匹配:
  SELECT * FROM employees WHERE name LIKE 'A%';  -- 匹配以 'A' 开头的名字
  • 使用BETWEEN进行范围查询:
  SELECT * FROM employees WHERE age BETWEEN 25 AND 35;
  • 使用ORDER BY排序:
  SELECT * FROM employees ORDER BY age DESC;  -- 按年龄降序排列
  • 使用LIMIT限制结果数量:
  SELECT * FROM employees LIMIT 5;  -- 只返回前 5 条记录
  • 使用GROUP BY分组:
  SELECT department, COUNT() AS employee_count 
  FROM employees 
  GROUP BY department;
  • 使用HAVING过滤分组结果:
  SELECT department, COUNT() AS employee_count 
  FROM employees 
  GROUP BY department 
  HAVING COUNT() > 2;
  • 使用JOIN连接多个表:
  SELECT e.name, d.department_name 
  FROM employees e 
  JOIN departments d ON e.department_id = d.id;
  • 使用子查询:
  SELECT * FROM employees WHERE salary > (SELECT AVG(salary) FROM employees);

4、数据控制语言(DCL)

DCL用于控制用户对数据库的访问权限。通过DCL,管理员可以授予或撤销用户的权限,确保数据的安全性和完整性。

常见的DCL操作包括:

  • GRANT:授予用户权限。
  • REVOKE:撤销用户权限。

使用示例:

  • 授予用户权限:(这条语句的作用是授予用户user1在主机localhost上对employees表的 SELECT和INSERT权限。)
  GRANT SELECT, INSERT ON employees TO 'user1'@'localhost';
  • 授予所有权限:(常用用户权限包含SELECT, INSERT, UPDATE, DELETE四个,ALL PRIVILEGES是所有权限,包含更多的操作)
  GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost';

说明:
SELECT, INSERT, UPDATE, DELETE和ALL PRIVILEGES区别

  • SELECT:允许用户查询表中的数据。

  • INSERT:允许用户向表中插入新数据。

  • UPDATE:允许用户更新表中的现有数据。

  • DELETE:允许用户从表中删除数据。
    这四个权限是数据库中最常用的权限,通常足以满足大多数用户的日常操作需求。它们只影响数据的操作,而不涉及数据库结构或系统级别的操作。ALL PRIVILEGES是一个更广泛的权限集合,它不仅包括SELECT, INSERT, UPDATE, DELETE,还包括以下权限:

  • CREATE:允许用户创建新的数据库、表、索引等。

  • DROP:允许用户删除数据库、表、索引等。

  • ALTER:允许用户修改表结构(如添加或删除列)。

  • INDEX:允许用户创建和删除索引。

  • GRANT OPTION:允许用户将自己拥有的权限授予其他用户。

  • REFERENCES:允许用户创建外键约束。

  • CREATE VIEW:允许用户创建视图。

  • SHOW VIEW:允许用户查看视图的定义。

  • CREATE ROUTINE:允许用户创建存储过程和函数。

  • ALTER ROUTINE:允许用户修改存储过程和函数。

  • EXECUTE:允许用户执行存储过程和函数。

  • FILE:允许用户读取和写入文件(例如通过LOAD DATA INFILE和SELECT … INTO OUTFILE)。

  • RELOAD:允许用户执行FLUSH操作,刷新服务器缓存。

  • SHUTDOWN:允许用户关闭MySQL服务器。

  • PROCESS:允许用户查看所有线程的状态。

  • SUPER:允许用户执行一些管理操作,如更改全局变量、杀死其他用户的线程、使用CHANGE MASTER TO等。

  • REPLICATION SLAVE:允许用户从主服务器复制数据。

  • REPLICATION CLIENT:允许用户获取主服务器和从服务器的状态信息。

  • 撤销用户权限:

  REVOKE SELECT, INSERT ON employees FROM 'user1'@'localhost';
  • 撤销所有权限:
  REVOKE ALL PRIVILEGES ON *.* FROM 'admin'@'localhost';

附用户相关操作语句

  • 创建用户:
  CREATE USER 'user1'@'localhost' IDENTIFIED BY 'password123';
  • 修改用户密码:
  ALTER USER 'user1'@'localhost' IDENTIFIED BY 'new_password';
  • 删除用户:
  DROP USER 'user1'@'localhost';
  • 重命名用户:
  RENAME USER 'user1'@'localhost' TO 'user2'@'localhost';
  • 查看当前用户:
  SELECT CURRENT_USER();
  • 查看所有用户:
  SELECT User, Host FROM mysql.user;

附:角色管理(Role Management)
从MySQL 8.0开始,MySQL引入了角色(Role)的概念,允许你将一组权限分配给一个角色,然后将该角色分配给多个用户。角色可以简化权限管理,特别是在有大量用户和复杂权限需求的情况下。

  • 创建角色:
  CREATE ROLE 'data_analyst';
  • 为角色分配权限:
 GRANT SELECT, INSERT, UPDATE ON mydatabase.* TO 'data_analyst';
  • 将角色分配给用户:
 GRANT 'data_analyst' TO 'user1'@'localhost';
  • 激活角色(角色授权):
 SET DEFAULT ROLE 'data_analyst' TO 'user1'@'localhost';
  • 查看用户的角色:
 SHOW GRANTS FOR 'user1'@'localhost';
  • 删除角色:
  DROP ROLE 'data_analyst';

5、事务控制语言(TCL)

TCL用于管理事务,确保一组相关的数据库操作要么全部成功,要么全部失败。事务的四个特性(ACID)保证了数据的一致性和可靠性。

常见的TCL操作包括:

  • BEGIN/START TRANSACTION:开始一个事务。
  • COMMIT:提交事务,使所有更改永久生效。
  • ROLLBACK:回滚事务,撤销所有未提交的更改。
  • SAVEPOINT:设置保存点,允许部分回滚。

使用示例:

  • 开始事务:
  START TRANSACTION;
  • 提交事务:
  COMMIT;
  • 回滚事务:
  ROLLBACK;
  • 设置保存点:
  SAVEPOINT my_savepoint;
  • 回滚到保存点:
  ROLLBACK TO SAVEPOINT my_savepoint;
  • 释放保存点:
  RELEASE SAVEPOINT my_savepoint;

6、SQL的高级功能

除了上述基本功能,SQL还提供了许多高级功能,用于处理复杂的数据操作和查询优化。以下是一些常见的高级SQL功能:

1、窗口函数(Window Functions)

窗口函数(Window Functions)是SQL中一种强大的工具,允许你在查询结果集中进行复杂的聚合计算,而不需要使用子查询或自连接。窗口函数可以在每一行数据上应用聚合操作,并且可以基于特定的分组、排序和范围来计算结果。MySQL从8.0版本开始支持窗口函数,极大地增强了其处理复杂查询的能力。

窗口函数的语法结构:

window_function([expression]) OVER (
    [PARTITION BY partition_expression]
    [ORDER BY sort_expression]
    [frame_clause]
)

说明:

  • window_function:指定要使用的窗口函数,如ROW_NUMBER()、RANK()、SUM()、AVG()等。
  • PARTITION BY:将结果集划分为多个分区(类似于GROUP BY),每个分区独立计算窗口函数的结果。
  • ORDER BY:在每个分区内对行进行排序,影响窗口函数的计算顺序。
  • frame_clause:定义窗口框架,指定窗口函数作用的行范围(可选)。常见的框架类型包括:
    • ROWS BETWEEN … AND …
    • RANGE BETWEEN … AND …

窗口函数示例:
窗口函数常用于在查询结果集中进行复杂的聚合计算,而不需要使用子查询或自连接。

(1)、ROW_NUMBER()

ROW_NUMBER()为每一行分配一个唯一的行号,行号从1开始,按ORDER BY指定的顺序递增。如果使用了PARTITION BY,则每个分区内的行号从1开始重新计数。

示例:为每个部门的员工分配行号

SELECT 
    department, 
    name, 
    salary, 
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS row_num
FROM 
    employees;

解释:

  • PARTITION BY department:按部门划分分区。
  • ORDER BY salary DESC:在每个部门内按工资降序排列。
  • ROW_NUMBER():为每个部门的员工分配行号,行号从1开始。

输出结果:
在这里插入图片描述

(2)、RANK()

RANK()为每一行分配一个排名,排名从1开始,按ORDER BY指定的顺序递增。如果有并列的行(即相同的排序值),它们会获得相同的排名,后续行的排名会跳过相应的数字。

示例:为每个部门的员工按工资排名
别名不要用关键字rank,否则语法执行错误。

SELECT 
    department, 
    name, 
    salary, 
    RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS rank1
FROM 
    employees;

解释:

  • PARTITION BY department:按部门划分分区。
  • ORDER BY salary DESC:在每个部门内按工资降序排列。
  • RANK():为每个部门的员工按工资排名,如果有并列的行,排名会跳过。

输出结果:
在这里插入图片描述

(3)、DENSE_RANK()

DENSE_RANK()类似于RANK(),但它不会跳过排名。即使有并列的行,后续行的排名也不会跳过。在上面的RANK示例中我们看到排名为(1,2,2,4,没有第3名),而DENSE_RANK()则会展示出第3名。

示例:为每个部门的员工按工资排名(不跳过)
别名不要用关键字dense_rank,否则语法执行错误。

SELECT 
    department, 
    name, 
    salary, 
    DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dense_rank1
FROM 
    employees;

解释:

  • PARTITION BY department:按部门划分分区。
  • ORDER BY salary DESC:在每个部门内按工资降序排列。
  • DENSE_RANK():为每个部门的员工按工资排名,即使有并列的行,排名也不会跳过。

输出结果:
在这里插入图片描述

(4)、NTILE(n)

NTILE(n)将结果集划分为n个桶(或分组),并为每一行分配一个桶编号。桶的大小尽可能均匀分布。

示例:将员工按工资分为4个等级

SELECT 
    name, 
    salary, 
    NTILE(4) OVER (ORDER BY salary DESC) AS salary_grade
FROM 
    employees;

解释:

  • ORDER BY salary DESC:按工资降序排列。
  • NTILE(4):将员工按工资分为4个等级,每个等级分配一个桶编号。
    输出结果:
    在这里插入图片描述
(5)、LAG()和LEAD()

LAG()和LEAD()用于访问当前行之前的行或之后的行的数据。LAG()访问前一行,LEAD()访问后一行。你可以指定偏移量(默认为1),并提供默认值(当没有前/后行时返回)。

示例:比较员工与其前一名员工的工资差额

SELECT 
    name, 
    salary, 
    LAG(salary, 1, 0) OVER (ORDER BY salary DESC) AS prev_salary,
    salary - LAG(salary, 1, 0) OVER (ORDER BY salary DESC) AS salary_diff
FROM 
    employees;

解释:

  • LAG(salary, 1, 0):获取前一行的工资,如果没有前一行则返回0。
  • salary - LAG(salary, 1, 0):计算当前行与前一行的工资差额。
    输出结果:
    在这里插入图片描述
    在这里插入图片描述
(6)、FIRST_VALUE()和LAST_VALUE()

FIRST_VALUE()返回窗口中第一个值,LAST_VALUE()返回窗口中最后一个值。你可以通过ORDER BY控制窗口中的排序顺序。

示例:获取每个部门中最高和最低工资的员工

SELECT 
    department, 
    name, 
    salary, 
    FIRST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary DESC) AS highest_salary,
    LAST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary DESC RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS lowest_salary
FROM 
    employees;

解释:

  • FIRST_VALUE(salary):获取每个部门中工资最高的员工的工资。
  • LAST_VALUE(salary):获取每个部门中工资最低的员工的工资。为了确保LAST_VALUE()返回最后一个值,我们使RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING 来定义窗口框架。
    窗口框架常用范围说明:
  • UNBOUNDED PRECEDING:表示从窗口的最开始(第一行)。
  • UNBOUNDED FOLLOWING:表示到窗口的最后(最后一行)。
  • CURRENT ROW:表示当前行。
  • n PRECEDING 或 n FOLLOWING:表示从前/后n行开始或结束。
    输出结果:
    在这里插入图片描述
(7)、SUM()、AVG()、MIN()、MAX()

这些聚合函数也可以作为窗口函数使用,允许你在每个分区或整个结果集中进行聚合计算,而不需要使用GROUP BY。

示例:计算每个部门的累计工资

SELECT 
    department, 
    name, 
    salary, 
    SUM(salary) OVER (PARTITION BY department ORDER BY salary DESC) AS cumulative_salary
FROM 
    employees;

解释:

  • SUM(salary):计算每个部门的累计工资。
  • PARTITION BY department:按部门划分分区。
  • ORDER BY salary DESC:在每个部门内按工资降序排列,确保累计工资按工资从高到低累加。
    输出结果:
    在这里插入图片描述

以上示例展示了聚合函数在窗口函数中的使用。聚合函数也可以不使用窗口函数,直接使用。
示例:求出每个部门的工资总和

SELECT
	department,
	SUM(salary)
FROM
	employees
GROUP BY
	department;

运行结果:
在这里插入图片描述

2、窗口框架(Frame Clause)

窗口框架允许你进一步控制窗口函数的作用范围。你可以指定窗口函数作用的行范围。

常用的框架类型包括:

  • ROWS BETWEEN … AND …:基于行数定义窗口框架。
  • RANGE BETWEEN … AND …:基于值的范围定义窗口框架。
(1)、ROWS BETWEEN

ROWS BETWEEN基于行数定义窗口框架。你可以指定窗口函数作用的前几行或后几行。

示例:计算每个员工及其前两行的平均工资

SELECT 
    name, 
    salary, 
    AVG(salary) OVER (ORDER BY salary DESC ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS avg_salary
FROM 
    employees;

解释:

  • ROWS BETWEEN 2 PRECEDING AND CURRENT ROW:窗口框架范围为前2行到当前行。
  • AVG(salary):计算当前行及其前两行的平均工资。
    常用范围说明:
  • UNBOUNDED PRECEDING:表示从窗口的最开始(第一行)。
  • UNBOUNDED FOLLOWING:表示到窗口的最后(最后一行)。
  • CURRENT ROW:表示当前行。
  • n PRECEDING 或 n FOLLOWING:表示从前/后n行开始或结束。
    输出结果:
    在这里插入图片描述
(2)、RANGE BETWEEN

RANGE BETWEEN基于值的范围定义窗口框架。它适用于数值类型的列,窗口框架基于值的差异而不是行数。

示例:计算每个员工及其工资相同或相差不超过5000的其他员工的平均工资

SELECT 
    name, 
    salary, 
    AVG(salary) OVER (ORDER BY salary DESC RANGE BETWEEN 5000 PRECEDING AND 5000 FOLLOWING) AS avg_salary
FROM 
    employees;

解释:

  • RANGE BETWEEN 5000 PRECEDING AND 5000 FOLLOWING:窗口框架包括当前行及其工资相差不超过5000的其他行。
  • AVG(salary):计算当前行及其工资相差不超过5000的其他行的平均工资。
    输出结果:
    在这里插入图片描述
    如果只是和高于自己最高5000的工资一起求平均值,如下:
    在这里插入图片描述

窗口函数总结:
窗口函数是MySQL 8.0及更高版本中非常强大的功能,能够让你在查询结果集中进行复杂的聚合计算,而不需要使用子查询或自连接。
常见的窗口函数包括:

  • ROW_NUMBER():为每一行分配唯一的行号。
  • RANK()和DENSE_RANK():为每一行分配排名。
  • NTILE(n):将结果集划分为n个桶。
  • LAG()和LEAD():访问前一行或后一行的数据。
  • FIRST_VALUE()和LAST_VALUE():获取窗口中的第一个或最后一个值。
  • SUM()、AVG()、MIN()、MAX():在窗口中进行聚合计算。
    此外,窗口框架(ROWS BETWEEN和RANGE BETWEEN)允许你进一步控制窗口函数的作用范围,使你能够更灵活地定义计算的上下文。

3、公用表表达式(CTE)

用于将复杂的查询分解为多个简单的步骤,提高可读性和维护性。CTE可以递归使用,适用于处理层次结构数据(如组织结构图、树形结构等)。

示例:

  WITH RECURSIVE org_tree AS (
      SELECT id, name, manager_id
      FROM employees
      WHERE manager_id IS NULL
      UNION ALL
      SELECT e.id, e.name, e.manager_id
      FROM employees e
      INNER JOIN org_tree ot ON e.manager_id = ot.id
  )
  SELECT * FROM org_tree;

运行结果:
在这里插入图片描述

4、临时表(Temporary Tables)

用于存储中间结果,避免重复计算。临时表只在当前会话中可见,会话结束后自动删除。

示例:创建一个临时表并使用临时表

CREATE TEMPORARY TABLE temp_employees AS
  SELECT * FROM employees WHERE department = 'HR';
select * from temp_employees;

运行结果:
在这里插入图片描述

5、索引(Indexes)

用于加速查询操作,特别是在大表上。索引可以显著提高查询性能,但也会影响插入、更新和删除操作的速度。常见的索引类型包括B-tree索引、哈希索引、全文索引等。

创建索引示例:

  CREATE INDEX idx_name ON employees (name);

6、视图(Views)

用于创建虚拟表,封装复杂的查询逻辑。视图可以简化查询,隐藏底层表的复杂性,并提供数据抽象。

示例:

  CREATE VIEW hr_employees AS
  SELECT * FROM employees WHERE department = 'HR';

7、存储过程(Stored Procedures)

用于封装一组SQL语句,作为可复用的代码块。存储过程可以接受参数、执行复杂的业务逻辑,并返回结果。

示例:创建一个存储过程,指定id查询对应的数据

  DELIMITER //
  CREATE PROCEDURE get_employee_by_id(IN emp_id INT)
  BEGIN
      SELECT * FROM employees WHERE id = emp_id;
  END //
  DELIMITER ;

解释:

  • DELIMITER //:更改MySQL的语句分隔符为//。默认情况下,MySQL使用分号;作为语句的结束符。然而,在创建存储过程时,存储过程体内部可能包含多个SQL语句,每个语句以分号结束。为了避免MySQL将这些内部的分号误认为是整个存储过程定义的结束,我们需要临时更改分隔符。这样MySQL会将整个存储过程定义视为一个完整的语句,直到遇到//才执行。
  • CREATE PROCEDURE get_employee_by_id(IN emp_id INT):创建一个名称为get_employee_by_id的存储过程。定义了一个输入参数emp_id,类型为INT。IN表示这是一个输入参数,即调用存储过程时需要传递的值。emp_id是你要查询的员工ID。
  • BEGIN和END:用于包裹存储过程的主体部分。在BEGIN和END之间的所有SQL语句都属于该存储过程的逻辑。本例中,存储过程体只包含一条SELECT语句,用于从employees表中查询与emp_id匹配的员工信息。
  • DELIMITER ; :将分隔符恢复为默认的分号;。这一步是为了确保后续的SQL语句使用默认的分隔符。
    运行结果:
    在这里插入图片描述
    调用存储过程示例:
CALL get_employee_by_id(10001);

在这里插入图片描述

8、触发器(Triggers)

用于在特定事件发生时自动执行一组SQL语句。触发器通常用于实现数据完整性约束、审计日志记录等功能。

示例:创建触发器(校验employees表新增的数据,age小于18岁时提示报错)

  CREATE TRIGGER before_insert_employee
  BEFORE INSERT ON employees
  FOR EACH ROW
  BEGIN
      IF NEW.age < 18 THEN
          SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Employee must be at least 18 years old';
      END IF;
  END;

解释:

  • CREATE TRIGGER before_insert_employee:创建一个名称为before_insert_employee的触发器。
  • BEFORE INSERT ON employees:指定触发器的执行时机。在employees表执行Insert语句之前触发。
  • FOR EACH ROW:指定触发器的执行粒度。FOR EACH ROW表示触发器会为每一行插入操作单独执行一次。也就是说,如果你一次性插入多条记录,触发器会为每一条记录分别检查条件。
  • BEGIN和END:用于包裹触发器的主体部分。在BEGIN和END之间的所有逻辑都属于该触发器的执行内容。在这个例子中,触发器体包含一个IF语句,用于检查新插入的员工年龄是否小于18岁。如果条件成立,则抛出一个错误,阻止插入操作。
  • IF NEW.age < 18 THEN:在触发器中,NEW是一个特殊的关键字,表示即将插入的新记录。它允许你在触发器中访问新记录的各个字段值。如果IF条件成立(即NEW.age < 18),则执行THEN后面的逻辑。
  • SIGNAL SQLSTATE ‘45000’ SET MESSAGE_TEXT = ‘Employee must be at least 18 years old’; : SIGNAL语句可以让你在触发器或存储过程中显式地抛出错误,从而中断当前的操作。45000是MySQL中的一个通用错误代码,表示“未分类的SQL状态”(unclassified SQL state)。你可以使用这个代码来抛出自定义的错误。SET MESSAGE_TEXT = 'Employee must be at least 18 years old’设置错误消息的内容。当触发器抛出错误时,MySQL会返回这条消息给客户端,告知用户具体的错误原因。
  • END IF;:结束IF语句的逻辑块。如果没有抛出错误,触发器将继续执行后续的逻辑(如果有)。
    执行结果:
    在这里插入图片描述
    验证触发器功能:
INSERT INTO employees VALUES ('10009', 'Alice', '16', 'HR', '70000', NULL)

在这里插入图片描述

7、SQL的优化技巧

为了提高SQL查询的性能,以下是几种常见的优化技巧:

  • 使用索引:为经常用于查询条件的列创建索引,以加速查询操作。避免在频繁更新的列上创建索引,因为索引会增加写操作的开销。
  • 避免全表扫描:尽量使用索引覆盖查询,确保查询只访问必要的数据。避免使用 SELECT *,只选择需要的列。
  • 合理使用JOIN:尽量减少JOIN的数量,避免不必要的连接。如果可能,使用子查询代替复杂的JOIN。
  • 使用合适的数据类型:选择合适的数据类型可以减少存储空间并提高查询性能。例如,使用INT代替VARCHAR存储数字,使用DATE代替VARCHAR存储日期。
  • 分页查询:对于大数据集,使用LIMIT和OFFSET进行分页查询,避免一次性加载过多数据。也可以考虑使用键集分页(Keyset Pagination)来提高分页性能。
  • 使用缓存:对于频繁执行的查询,可以使用查询缓存(如MySQL的查询缓存或应用层缓存)来减少数据库的压力。
  • 分析查询计划:使用EXPLAIN语句分析查询的执行计划,找出潜在的性能瓶颈。根据分析结果调整查询语句或索引。
    示例:
 EXPLAIN SELECT * FROM employees WHERE department = 'HR';

8、SQL总结

SQL是一种强大且灵活的查询语言,广泛应用于关系型数据库的管理和操作。通过掌握SQL的各个组成部分(DDL、DML、DQL、DCL 和 TCL),你可以有效地创建、修改、查询和管理数据库中的数据。此外,SQL 还提供了许多高级功能,如窗口函数、CTE、索引、视图等,帮助你处理复杂的业务需求和优化查询性能。

仰天大笑出门去,我辈岂是蓬蒿人!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2272638.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Excel重新踩坑5:二级下拉列表制作;★数据透视表;

0、在excel中函数公式不仅可以写在单元格里面&#xff0c;还可以写在公式里面。 1、二级下拉列表制作&#xff1a; 2、数据透视表&#xff1a; 概念&#xff1a;通过拖拉就能实现复杂函数才能实现的数据统计问题。 概览&#xff1a;在插入选项中有个数据透视表&#xff0c;数…

Linux-----进程处理(waitpid,进程树,孤儿进程)

目录 waitpid等待 进程树 孤儿进程 waitpid等待 Linux中父进程除了可以启动子进程&#xff0c;还要负责回收子进程的状态。如果子进程结束后父进程没有正常回收&#xff0c;那么子进程就会变成一个僵尸进程——即程序执行完成&#xff0c;但是进程没有完全结束&#xff0c;其…

解决报错net.sf.jsqlparser.statement.select.SelectBody

在我们项目集成mybatis-plus时,总会遇到奇奇怪怪的报错,比如说下面的这个报错 而这个报错,是告诉我们的分页依赖冲突,要加个jsqlparser依赖来解决这个冲突,也相当于平衡,但是可能因为我们版本的不匹配,还是会报错,例如下面这样 但是我们是不知道到底是什么依赖冲突的,这个时候就…

感知器的那些事

感知器的那些事 历史背景Rosenblatt和Minsky关于感知机的争论弗兰克罗森布拉特简介提出感知器算法Mark I感知机争议与分歧马文明斯基简介单层感知器工作原理训练过程多层感知器工作原理单层感知机 vs 多层感知机感知器模型(Perceptron),是由心理学家Frank Rosenblatt在1957年…

内核链表 例题 C语言实现

问题&#xff1a; 将下面的数据节点信息转换为链表结构&#xff0c;并遍历输出。要求根据type的值来决定val的类型。 type为1代表bool类型&#xff0c;2代表整形&#xff0c;3代表浮点型。无需解析文本&#xff0c;直接赋值形成节点即可。 代码&#xff1a; list.c #includ…

C语言结构体数组

上次我们讲解了结构体&#xff0c;这里还有高级应用就是结构体数组&#xff08;集合的集合&#xff09; &#xff08;这里提醒一句&#xff0c;想要在北京参加NCRE考试的朋友们今天开始报名了&#xff09; 定义 还是拿上回那个学生数据的结构体 typedef struct {int year;i…

深入了解 ES6 Map:用法与实践

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

在Vue3项目中使用svg-sprite-loader

1.普通的svg图片使用方式 1.1 路径引入 正常我们会把项目中的静态资源放在指定的一个目录&#xff0c;例如assets,使用起来就像 <img src"../assets/svgicons/about.svg" /> 1.2封装组件使用 显然上面的这种方法在项目开发中不太适用&#xff0c;每次都需…

谷歌SEO真的需要很长时间吗?

关键在于策略与执行力&#xff0c;很多人在刚开始做谷歌SEO时&#xff0c;都会产生一种挫败感&#xff0c;觉得排名变化太慢&#xff0c;看不到显著效果。这其实是因为SEO本身是一项需要时间的工作&#xff0c;特别是在竞争激烈的领域。但如果策略得当、执行力强&#xff0c;时…

耐高压26V输入5V升压充电8.4V芯片

HU6877作为一款集成了26V高耐压保护的5V升压至8.4V两节锂电池充电管理IC&#xff0c;凭借其高效升压、智能充电管理、多重安全保护及高耐压特性&#xff0c;在高端手电筒、便携式医疗设备、无人机等领域展现出了广泛的应用前景。本文将详细探讨HU6877的技术特点、工作原理、应用…

linuxCNC(六)配置LinuxCNC完成伺服控制

这里写目录标题 1、 cia402安装2、找伺服描述文件&#xff08;xml&#xff09;3、配置ethercat-config.xml3.1、打开hal-cia402/example/ethercat-conf.xml3.2、修改 ethercat-conf.xml文件中vid"0x000116c7" pid"0x003e0402"3.3、其他参数&#xff0c;根据…

【数据结构】链表(2):双向链表和双向循环链表

双向链表&#xff08;Doubly Linked List&#xff09; 定义&#xff1a; 每个节点包含三个部分&#xff1a; 数据域。前驱指针域&#xff08;指向前一个节点&#xff09;。后继指针域&#xff08;指向下一个节点&#xff09;。 支持从任意节点向前或向后遍历。 #define dat…

指针 const 的组合

1、首先来了解一下常量 const int num 5&#xff1b; 那么num的值是5&#xff0c; num的值不可修改 2、来了解一下指针 int value 5; int* p &value; 我喜欢吧指针和类型放一起&#xff0c;来强调p是一个指针类型&#xff0c; 而赋值的时候就得赋值一个int类型的地址…

Tableau数据可视化与仪表盘搭建-数据可视化原理

目录 内容 做个小实验 数据如何变成图表 1 2 维度和度量定义 3 度量映射图形&#xff0c;维度负责区分 1 可映射的数据类型 2 可视化字典 3 使用Tableau将数据变成图表(Tableau可视化原理) 1 2 拖拽 3 具体操作 4 总结 内容 点击左下角的工作表 tableau可以自动…

【WRF数据准备】气象驱动数据-ERA5是否需要单层位势数据?

目录 气象驱动数据-ERA5是否需要单层位势(Geopotential)数据?位势(Geopotential)输入的重要性Vtable的管理参考气象驱动数据-ERA5是否需要单层位势(Geopotential)数据? 本博客参考WRF论坛中讨论内容-How to use ERA5 Data From Copernicus Database,总结位势(Geopot…

用ResNet50+Qwen2-VL-2B-Instruct+LoRA模仿Diffusion-VLA的论文思路,在3090显卡上训练和测试成功

想一步步的实现Diffusion VLA论文的思路&#xff0c;不过论文的图像的输入用DINOv2进行特征提取的&#xff0c;我先把这个部分换成ResNet50。 老铁们&#xff0c;直接上代码&#xff1a; from PIL import Image import torch import torchvision.models as models from torch…

常见中间件漏洞(tomcat,weblogic,jboss,apache)

先准备好今天要使用的木马文件 使用哥斯拉生成木马 压缩成zip文件 改名为war后缀 一&#xff1a;Tomcat 1.1CVE-2017-12615 环境搭建 cd vulhub-master/tomcat/CVE-2017-12615 docker-compose up -d 1.首页抓包&#xff0c;修改为 PUT 方式提交 发送shell.jsp 和木马内容 …

嵌入式科普(26)为什么heap通常8字节对齐

目录 一、概述 二、newlibc heap 2.1 stm32cubeide .ld heap 2.2 e2studio .ld heap 三、glibc源码 3.1 Ubuntu c heap 四、总结 一、概述 结论&#xff1a;在嵌入式c语言中&#xff0c;heap通常8字节对齐 本文主要分析这个问题的分析过程 二、newlibc heap newlibc…

大数据-240 离线数仓 - 广告业务 测试 ADS层数据加载 DataX数据导出到 MySQL

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…

CTF杂项——[NSSRound#4 SWPU]Pixel_Signin

得到一个像素点 提取像素点 脚本 from PIL import Image result open(1.txt,w) img Image.open("Pixel_Signin.png") img img.convert(RGB) for i in range(31):for j in range(31):r,g,b img.getpixel((j,i))print(r,g,b,end ,fileresult) 运行之后得到 把它…