当前位置: 首页 > ops >正文

SQL视图、存储过程和触发器

视图、存储过程和触发器是SQL中的重要数据库对象,用于封装业务逻辑、简化操作和保证数据完整性。它们在数据库开发中有着广泛应用,能够提高代码复用性和系统安全性。

一、视图(View)

视图是从一个或多个表中导出的虚拟表,它本身不存储数据,只保存查询定义。视图可以简化复杂查询,限制数据访问,提供数据独立性。

1. 视图的特点

- 虚拟表,不实际存储数据,数据来源于基础表

- 可以像表一样进行查询操作

- 基表数据变化时,视图数据会自动更新

- 可以限制用户访问的数据范围,提高安全性

2. 视图的创建

CREATE VIEW 视图名 AS
SELECT 字段1, 字段2, ...
FROM 表名
WHERE 条件;

示例:创建员工部门视图

CREATE VIEW employee_department AS
SELECT e.emp_id, e.emp_name, d.dept_name, e.salary
FROM employees e
INNER JOIN departments d ON e.dept_id = d.dept_id;

3. 视图的查询

查询视图与查询表的语法相同:

-- 查询销售部员工
SELECT * FROM employee_department
WHERE dept_name = '销售部';-- 统计各部门平均工资
SELECT dept_name, AVG(salary) AS avg_salary
FROM employee_department
GROUP BY dept_name;

4. 视图的修改

-- 方式1:CREATE OR REPLACE
CREATE OR REPLACE VIEW employee_department AS
SELECT e.emp_id, e.emp_name, d.dept_name, e.salary, e.hire_date
FROM employees e
INNER JOIN departments d ON e.dept_id = d.dept_id;-- 方式2:ALTER
ALTER VIEW employee_department AS
SELECT e.emp_id, e.emp_name, d.dept_name
FROM employees e
INNER JOIN departments d ON e.dept_id = d.dept_id;

5. 视图的删除

DROP VIEW IF EXISTS employee_department;

6. 视图的使用场景

- 简化复杂查询,将常用的多表查询封装为视图

- 限制用户访问敏感数据(如只暴露部分字段)

- 提供数据独立性,当基表结构变化时,可通过修改视图保持接口稳定

7. 视图的注意事项

- 大部分视图可更新(INSERT/UPDATE/DELETE),但有诸多限制(如不能包含聚合函数、DISTINCT等)

- 复杂视图查询性能可能较差,避免在视图上再创建视图

- 视图不适合频繁更新的场景

二、存储过程(Stored Procedure)

存储过程是预编译并存储在数据库中的一组SQL语句集合,可通过名称和参数调用。它能封装复杂业务逻辑,减少网络传输,提高执行效率。

1. 存储过程的特点

- 预编译存储,多次执行效率高

- 可包含条件判断、循环等复杂逻辑

- 支持输入输出参数,增强灵活性

- 减少应用程序与数据库的交互次数

2. 存储过程的创建

DELIMITER //
CREATE PROCEDURE 存储过程名(参数列表)
BEGIN-- SQL语句集合
END //
DELIMITER ;

参数类型:

- IN:输入参数(默认)

- OUT:输出参数

- INOUT:既可以输入也可以输出

示例1:无参数存储过程(查询所有员工)

DELIMITER //
CREATE PROCEDURE get_all_employees()
BEGINSELECT * FROM employees;
END //
DELIMITER ;

示例2:带输入参数的存储过程(查询指定部门员工)

DELIMITER //
CREATE PROCEDURE get_employees_by_dept(IN dept_id INT)
BEGINSELECT e.emp_id, e.emp_name, d.dept_nameFROM employees eINNER JOIN departments d ON e.dept_id = d.dept_idWHERE e.dept_id = dept_id;
END //
DELIMITER ;

示例3:带输出参数的存储过程(统计部门员工数)

DELIMITER //
CREATE PROCEDURE count_employees_by_dept(IN dept_id INT,OUT emp_count INT
)
BEGINSELECT COUNT(*) INTO emp_countFROM employeesWHERE employees.dept_id = dept_id;
END //
DELIMITER ;

3. 存储过程的调用

-- 调用无参数存储过程
CALL get_all_employees();-- 调用带输入参数的存储过程
CALL get_employees_by_dept(1);-- 调用带输出参数的存储过程
SET @count = 0;
CALL count_employees_by_dept(1, @count);
SELECT @count AS employee_count;

4. 存储过程的修改与删除

-- 修改存储过程(MySQL中需先删除再重建)
DROP PROCEDURE IF EXISTS get_all_employees;-- 删除存储过程
DROP PROCEDURE IF EXISTS get_employees_by_dept;

5. 存储过程中的控制结构

(1)条件判断

DELIMITER //
CREATE PROCEDURE check_salary(IN emp_id INT)
BEGINDECLARE emp_salary DECIMAL(10,2);SELECT salary INTO emp_salary FROM employees WHERE id = emp_id;IF emp_salary > 10000 THENSELECT '高薪员工' AS result;ELSEIF emp_salary > 5000 THENSELECT '中等收入' AS result;ELSESELECT '低收入' AS result;END IF;
END //
DELIMITER ;

(2)循环结构

DELIMITER //
CREATE PROCEDURE insert_test_data(IN count INT)
BEGINDECLARE i INT DEFAULT 1;WHILE i <= count DOINSERT INTO test (name) VALUES (CONCAT('test_', i));SET i = i + 1;END WHILE;
END //
DELIMITER ;

6. 存储过程的使用场景

- 复杂业务逻辑处理(如订单创建、支付流程)

- 批量数据处理(如数据迁移、批量插入)

- 需要多次执行的SQL语句集合

- 增强数据库安全性(限制直接表访问,通过存储过程操作)

三、触发器(Trigger)

触发器是与表关联的特殊存储过程,当表发生特定事件(INSERT、UPDATE、DELETE)时自动执行。它主要用于保证数据完整性和实现复杂业务规则。

1. 触发器的特点

- 自动触发,无需手动调用

- 与特定表和事件关联

- 可在事件发生前(BEFORE)或后(AFTER)执行

- 常用于数据校验、日志记录、级联操作等

2. 触发器的创建

DELIMITER //
CREATE TRIGGER 触发器名
触发时机(BEFORE/AFTER) 触发事件(INSERT/UPDATE/DELETE)
ON 表名 FOR EACH ROW
BEGIN-- 触发器执行的SQL语句
END //
DELIMITER ;

特殊变量:

- NEW:表示新插入或更新后的数据(仅用于INSERT和UPDATE)

- OLD:表示更新前或删除的数据(仅用于UPDATE和DELETE)

示例1:插入前验证数据(确保工资为正数)

DELIMITER //
CREATE TRIGGER check_salary_before_insert
BEFORE INSERT ON employees
FOR EACH ROW
BEGINIF NEW.salary <= 0 THENSIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '工资必须大于0';END IF;
END //
DELIMITER ;

示例2:更新后记录日志(记录工资变动)

DELIMITER //
CREATE TRIGGER log_salary_change
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN-- 当工资发生变化时记录日志IF OLD.salary != NEW.salary THENINSERT INTO salary_logs (emp_id, old_salary, new_salary, change_time)VALUES (OLD.emp_id, OLD.salary, NEW.salary, NOW());END IF;
END //
DELIMITER ;

示例3:删除时级联操作(删除部门前先处理员工)

DELIMITER //
CREATE TRIGGER handle_department_delete
BEFORE DELETE ON departments
FOR EACH ROW
BEGIN-- 将该部门员工移至默认部门(ID=0)UPDATE employees SET dept_id = 0 WHERE dept_id = OLD.dept_id;
END //
DELIMITER ;

3. 触发器的查看与删除

-- 查看触发器
SHOW TRIGGERS;-- 查看特定表的触发器
SHOW TRIGGERS LIKE 'employees';-- 删除触发器
DROP TRIGGER IF EXISTS check_salary_before_insert;

4. 触发器的使用场景

- 数据校验(如确保字段值符合业务规则)

- 自动记录日志(如数据修改历史)

- 实现级联操作(如删除主表记录时处理关联表)

- 维护衍生数据(如自动计算汇总值)

5. 触发器的注意事项

- 避免在触发器中执行复杂操作,以免影响性能

- 触发器中不能直接引用该表本身,可能导致循环触发

- 过多触发器会使数据逻辑复杂化,增加维护难度

- 触发器执行失败会导致原操作(INSERT/UPDATE/DELETE)失败

四、视图、存储过程和触发器的比较

1. 视图:虚拟表,主要用于简化查询和控制数据访问,无逻辑处理能力

2. 存储过程:需手动调用,可包含复杂逻辑,适合封装业务流程

3. 触发器:自动触发,与表事件关联,适合数据完整性维护和自动响应

五、最佳实践

1. 适度使用:避免过度依赖这些对象,简单逻辑可在应用程序中实现

2. 命名规范:为视图、存储过程和触发器制定清晰的命名规则,如:

- 视图:v_xxx

- 存储过程:sp_xxx

- 触发器:tr_xxx_before_insert

3. 文档化:对复杂的存储过程和触发器进行文档说明,便于维护

4. 测试:修改这些数据库对象后需充分测试,避免影响现有功能

5. 性能监控:定期检查这些对象的执行性能,优化低效代码

http://www.xdnf.cn/news/18312.html

相关文章:

  • npm全局安装后,cmd命令行可以访问,vscode访问报错
  • Django REST框架核心:GenericAPIView详解
  • GitHub Push 认证失败 fatal Authentication failed
  • OceanBase 分区裁剪(Partition Pruning)原理解读
  • Binlog Server守护MySQL数据0丢失
  • 基于Pytochvideo训练自己的的视频分类模型
  • python中view把矩阵维度降低的时候是什么一个排序顺序
  • 机器学习——数据清洗
  • 【论文阅读】Multi-metrics adaptively identifies backdoors in Federated Learning
  • Linux 文本处理与 Shell 编程笔记:正则表达式、sed、awk 与变量脚本
  • 本地文件上传到gitee仓库的详细步骤
  • Excel表格复制到word中格式错乱
  • Nginx 的完整配置文件结构、配置语法以及模块详解
  • 【学习笔记】大话设计模式——一些心得及各设计模式思想记录
  • Vue3全局配置Loading的完整指南:从基础到实战
  • PyTorch API 4
  • Mac 4步 安装 Jenv 管理多版本JDK
  • Linux Capability 解析
  • strncpy 函数使用及其模拟实现
  • 为什么我的UI界面会突然卡顿,失去响应
  • 安装使用Conda
  • pyqt 的自动滚动区QScrollArea
  • Rust 入门 包 (二十一)
  • Ubuntu 虚拟显示器自动控制服务设置(有无显示器的切换)
  • 华为数通认证学习
  • 微算法科技(NASDAQ: MLGO)引入高级区块链DSR算法:重塑区块链网络安全新范式
  • K8S-Configmap资源
  • C++中的 Eigen库使用
  • 数据库DML语言(增、删、改)
  • oracle服务器导入dmp文件