引言
各位数据库爱好者们好!今天我们要探索MySQL中两个强大的自动化工具------函数和触发器 🚀。函数就像数据库中的"瑞士军刀",能帮你高效处理各种数据;而触发器则是数据库的"自动感应器",能在数据变化时自动执行操作。掌握这些功能,你将能构建更加智能、自动化的数据库系统!本教程将带你从内置函数到自定义开发,从触发器基础到高级应用,全面提升你的MySQL自动化技能!💪
一、MySQL内置函数大全
1.1 字符串处理函数:文本操作利器
字符串函数就像文字编辑工具,帮你轻松处理文本数据 ✂️:
常用字符串函数:
sql
-- 连接字符串
SELECT CONCAT('Hello', ' ', 'World'); -- Hello World
SELECT CONCAT_WS('-', '2023', '01', '01'); -- 2023-01-01
-- 大小写转换
SELECT LOWER('MySQL'); -- mysql
SELECT UPPER('mysql'); -- MYSQL
-- 截取与填充
SELECT SUBSTRING('2023-01-15', 6, 2); -- 01
SELECT LPAD(5, 3, '0'); -- 005
SELECT TRIM(' MySQL '); -- MySQL
-- 查找与替换
SELECT INSTR('MySQL', 'SQL'); -- 3
SELECT REPLACE('I use Oracle', 'Oracle', 'MySQL'); -- I use MySQL
-- 正则表达式(MySQL 8.0+)
SELECT REGEXP_LIKE('abc123', '^[a-z]+[0-9]+$'); -- 1
SELECT REGEXP_REPLACE('abc123', '[0-9]', 'X'); -- abcXXX
1.2 数值计算函数:数学运算专家
数值函数就像计算器,帮你完成各种数学运算 🧮:
常用数值函数:
sql
-- 基本运算
SELECT ABS(-10); -- 10
SELECT MOD(15, 4); -- 3
SELECT POW(2, 3); -- 8
SELECT ROUND(3.1415, 2); -- 3.14
SELECT TRUNCATE(3.1415, 2); -- 3.14 (直接截断)
-- 随机数
SELECT RAND(); -- 0-1之间的随机数
SELECT FLOOR(1 + RAND() * 10); -- 1-10的随机整数
-- 数学函数
SELECT SQRT(16); -- 4
SELECT LOG(2, 8); -- 3
SELECT SIN(PI()/2); -- 1
-- 聚合函数
SELECT AVG(salary) FROM employees;
SELECT SUM(quantity*price) FROM order_items;
1.3 日期时间函数:时间管理大师
日期函数就像日历和闹钟,帮你处理时间数据 ⏰:
常用日期函数:
sql
-- 当前时间
SELECT NOW(); -- 2023-01-15 14:30:00
SELECT CURDATE(); -- 2023-01-15
SELECT CURTIME(); -- 14:30:00
-- 日期解析
SELECT YEAR('2023-01-15'); -- 2023
SELECT MONTHNAME('2023-01-15'); -- January
SELECT DAYOFWEEK('2023-01-15'); -- 1(周日)
-- 日期计算
SELECT DATE_ADD('2023-01-15', INTERVAL 1 MONTH); -- 2023-02-15
SELECT DATEDIFF('2023-01-20', '2023-01-15'); -- 5
SELECT LAST_DAY('2023-01-15'); -- 2023-01-31
-- 格式化
SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日 %H:%i:%s'); -- 2023年01月15日 14:30:00
SELECT TIME_FORMAT('14:30:00', '%h:%i %p'); -- 02:30 PM
二、自定义函数:打造专属工具
2.1 创建自定义函数
自定义函数就像DIY工具,满足你的特殊需求 🛠️:
基本语法:
sql
DELIMITER //
CREATE FUNCTION 函数名(参数 数据类型, ...)
RETURNS 返回值类型
[DETERMINISTIC|NOT DETERMINISTIC]
BEGIN
-- 函数体
RETURN 返回值;
END //
DELIMITER ;
实际示例:
sql
-- 创建计算税后工资的函数
DELIMITER //
CREATE FUNCTION calculate_net_salary(
gross_salary DECIMAL(10,2),
tax_rate DECIMAL(5,2)
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGIN
DECLARE net_salary DECIMAL(10,2);
SET net_salary = gross_salary * (1 - tax_rate/100);
RETURN net_salary;
END //
DELIMITER ;
调用自定义函数:
sql
SELECT
employee_id,
salary,
calculate_net_salary(salary, 20) AS net_salary
FROM employees;
2.2 函数特性与限制
函数特性:
- 必须使用RETURN语句返回值
- 可以调用其他函数或存储过程
- 支持递归调用(有深度限制)
- 可以是确定性(DETERMINISTIC)或非确定性函数
与存储过程的区别:
特性 | 函数 | 存储过程 |
---|---|---|
返回值 | 必须返回一个值 | 可以没有或多个OUT参数 |
调用方式 | 在SQL语句中直接调用 | 使用CALL语句调用 |
事务控制 | 不能包含事务语句 | 可以包含完整事务 |
结果集 | 不能返回结果集 | 可以返回多个结果集 |
三、触发器:自动化数据守护者
3.1 触发器基础与创建
触发器就像数据库的"自动感应器",在数据变化时自动执行操作 🤖:
基本语法:
sql
DELIMITER //
CREATE TRIGGER 触发器名
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON 表名 FOR EACH ROW
BEGIN
-- 触发器逻辑
END //
DELIMITER ;
实际示例:
sql
-- 创建审计日志触发器
DELIMITER //
CREATE TRIGGER audit_employee_changes
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
IF NEW.salary <> OLD.salary THEN
INSERT INTO salary_change_logs(
employee_id,
old_salary,
new_salary,
change_time
) VALUES (
NEW.employee_id,
OLD.salary,
NEW.salary,
NOW()
);
END IF;
END //
DELIMITER ;
3.2 NEW与OLD关键字
在触发器中可以访问特殊记录:
- INSERT触发器:只有NEW可用
- UPDATE触发器:NEW和OLD都可用
- DELETE触发器:只有OLD可用
使用示例:
sql
-- 确保价格调整不超过10%
DELIMITER //
CREATE TRIGGER validate_price_change
BEFORE UPDATE ON products
FOR EACH ROW
BEGIN
DECLARE max_change DECIMAL(5,2);
SET max_change = 0.10; -- 最大10%变化
IF ABS((NEW.price - OLD.price) / OLD.price) > max_change THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '价格调整幅度不能超过10%';
END IF;
END //
DELIMITER ;
3.3 触发器管理
查看触发器:
sql
SHOW TRIGGERS;
SHOW TRIGGERS FROM database_name;
SHOW CREATE TRIGGER trigger_name;
修改触发器 :
MySQL不支持直接修改触发器,必须先删除再重建:
sql
DROP TRIGGER IF EXISTS trigger_name;
-- 然后重新创建
四、触发器高级应用场景
4.1 数据完整性维护
级联非主键更新:
sql
DELIMITER //
CREATE TRIGGER cascade_department_name
AFTER UPDATE ON departments
FOR EACH ROW
BEGIN
IF NEW.department_name <> OLD.department_name THEN
UPDATE employees
SET department_name = NEW.department_name
WHERE department_id = NEW.department_id;
END IF;
END //
DELIMITER ;
4.2 自动计算派生列
维护订单总金额:
sql
DELIMITER //
CREATE TRIGGER update_order_total
AFTER INSERT ON order_items
FOR EACH ROW
BEGIN
UPDATE orders
SET total_amount = (
SELECT SUM(quantity*price)
FROM order_items
WHERE order_id = NEW.order_id
)
WHERE order_id = NEW.order_id;
END //
DELIMITER ;
4.3 业务规则实施
限制库存不能为负:
sql
DELIMITER //
CREATE TRIGGER prevent_negative_inventory
BEFORE UPDATE ON products
FOR EACH ROW
BEGIN
IF NEW.stock_quantity < 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '库存数量不能为负数';
END IF;
END //
DELIMITER ;
五、函数与触发器实战案例
5.1 完整审计系统实现
创建审计表:
sql
CREATE TABLE audit_log (
log_id INT AUTO_INCREMENT PRIMARY KEY,
table_name VARCHAR(50) NOT NULL,
record_id INT NOT NULL,
action ENUM('INSERT','UPDATE','DELETE') NOT NULL,
change_time DATETIME NOT NULL,
user_name VARCHAR(50) NOT NULL,
old_data JSON,
new_data JSON
);
创建通用审计触发器:
sql
DELIMITER //
CREATE TRIGGER audit_employee_changes
AFTER INSERT OR UPDATE OR DELETE ON employees
FOR EACH ROW
BEGIN
DECLARE v_action VARCHAR(10);
DECLARE v_user VARCHAR(50);
-- 确定操作类型
IF INSERTING THEN
SET v_action = 'INSERT';
ELSEIF UPDATING THEN
SET v_action = 'UPDATE';
ELSE
SET v_action = 'DELETE';
END IF;
-- 获取当前用户
SET v_user = CURRENT_USER();
-- 插入审计记录
INSERT INTO audit_log (
table_name,
record_id,
action,
change_time,
user_name,
old_data,
new_data
) VALUES (
'employees',
COALESCE(NEW.employee_id, OLD.employee_id),
v_action,
NOW(),
v_user,
CASE WHEN v_action IN ('UPDATE','DELETE')
THEN JSON_OBJECT(
'employee_id', OLD.employee_id,
'first_name', OLD.first_name,
'last_name', OLD.last_name,
'salary', OLD.salary
)
ELSE NULL END,
CASE WHEN v_action IN ('INSERT','UPDATE')
THEN JSON_OBJECT(
'employee_id', NEW.employee_id,
'first_name', NEW.first_name,
'last_name', NEW.last_name,
'salary', NEW.salary
)
ELSE NULL END
);
END //
DELIMITER ;
5.2 数据加密函数实现
创建加密函数:
sql
DELIMITER //
CREATE FUNCTION encrypt_data(
plain_text VARCHAR(255),
secret_key VARCHAR(32)
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
-- 简单加密示例(实际项目应使用更强加密)
DECLARE encrypted_text VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 1;
DECLARE len INT;
DECLARE key_len INT;
SET len = LENGTH(plain_text);
SET key_len = LENGTH(secret_key);
WHILE i <= len DO
SET encrypted_text = CONCAT(
encrypted_text,
CHAR(ASCII(SUBSTRING(plain_text, i, 1)) +
ASCII(SUBSTRING(secret_key, (i % key_len) + 1, 1))
);
SET i = i + 1;
END WHILE;
RETURN encrypted_text;
END //
DELIMITER ;
-- 配套的解密函数
DELIMITER //
CREATE FUNCTION decrypt_data(
encrypted_text VARCHAR(255),
secret_key VARCHAR(32)
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
DECLARE plain_text VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 1;
DECLARE len INT;
DECLARE key_len INT;
SET len = LENGTH(encrypted_text);
SET key_len = LENGTH(secret_key);
WHILE i <= len DO
SET plain_text = CONCAT(
plain_text,
CHAR(ASCII(SUBSTRING(encrypted_text, i, 1)) -
ASCII(SUBSTRING(secret_key, (i % key_len) + 1, 1))
);
SET i = i + 1;
END WHILE;
RETURN plain_text;
END //
DELIMITER ;
总结 🎯
通过本教程,我们系统学习了MySQL函数和触发器的强大功能 🎓:
- 内置函数:掌握了字符串、数值、日期等各类内置函数的使用
- 自定义函数:学会了创建和使用自定义函数解决特定问题
- 触发器基础:理解了触发器的创建语法和基本应用
- 高级应用:探索了触发器在数据完整性、业务规则等方面的应用
关键收获:
- 函数是代码复用的重要手段
- 触发器能实现自动化数据管理
- NEW和OLD是触发器的特殊记录访问方式
- 合理使用函数和触发器可以简化应用逻辑
最佳实践建议:
- 为函数和触发器使用清晰的命名规范
- 添加充分的注释说明逻辑
- 避免在触发器中执行耗时操作
- 考虑性能影响,不要过度使用触发器
下一步学习建议:
- 在实际项目中应用所学函数和触发器
- 学习MySQL事件调度器实现定时任务
- 探索存储引擎的更高级特性
- 研究数据库设计模式和优化策略
PS:如果你在学习过程中遇到问题,别慌!欢迎在评论区留言,我会尽力帮你解决!😄