一、变量的定义 (DECLARE)
语法:
DECLARE var_name [, var_name2, ...] data_type [DEFAULT default_value];
关键点:
位置要求:`DECLARE` 语句必须放在 `BEGIN ... END` 块的开头,并且在所有其他可执行语句之前。
默认值:如果未使用 `DEFAULT` 子句,变量的初始值为 `NULL`。
作用域:变量只在声明的 `BEGIN ... END` 块及其嵌套块中有效。
示例:
DELIMITER //
CREATE PROCEDURE example_procedure()
BEGIN
必须在BEGIN后首先声明变量
DECLARE my_sql INT DEFAULT 10; 整型变量,默认值10
DECLARE student_name VARCHAR(50); 字符串变量,默认NULL
DECLARE total_price, discount DECIMAL(10,2); 同时声明多个同类型变量
DECLARE is_valid BOOLEAN DEFAULT TRUE; 布尔型变量
后续才是执行语句
END //
DELIMITER ;
二、为变量赋值 (SET)
语法:
SET var_name = expr [, var_name2 = expr2, ...];
示例:
BEGIN
DECLARE a, b, c INT;
DECLARE name VARCHAR(100);
DECLARE price DECIMAL(10,2);
简单赋值
SET a = 10;
表达式赋值
SET b = a * 2 + 5;
同时为多个变量赋值
SET a = 1, b = 2, c = 3;
使用函数赋值
SET name = CONCAT('John', ' ', 'Doe');
SET price = ROUND(99.99 * 0.9, 2);
使用查询结果赋值(需要保证查询返回单值)
SET @row_count = (SELECT COUNT(*) FROM tb_student);
END;
三、使用 SELECT...INTO 赋值
语法:
SELECT column1, column2, ...
INTO var1, var2, ...
FROM table_name
WHERE condition
[LIMIT 1];
重要特点:
必须返回单行:查询结果必须有且只有一行,否则会报错。
变量匹配:`SELECT` 的列数必须与 `INTO` 的变量数一致。
常用场景:根据主键查询、使用聚合函数等保证返回单行的查询。
示例:
BEGIN
DECLARE v_id INT;
DECLARE v_name VARCHAR(50);
DECLARE v_score DECIMAL(5,2);
DECLARE v_avg_score DECIMAL(5,2);
DECLARE v_count INT;
根据主键查询单条记录
SELECT id, name, score INTO v_id, v_name, v_score
FROM tb_student
WHERE id = 2;
使用聚合函数(保证返回单行)
SELECT AVG(score), COUNT(*) INTO v_avg_score, v_count
FROM tb_student;
使用LIMIT确保单行
SELECT name INTO v_name
FROM tb_student
WHERE score > 90
LIMIT 1;
END;
四、完整示例
DELIMITER //
CREATE PROCEDURE calculate_student_stats(IN student_id INT)
BEGIN
声明变量
DECLARE v_student_name VARCHAR(50);
DECLARE v_score DECIMAL(5,2);
DECLARE v_class_avg DECIMAL(5,2);
DECLARE v_performance VARCHAR(20);
使用SELECT...INTO获取学生信息
SELECT name, score INTO v_student_name, v_score
FROM tb_student
WHERE id = student_id;
使用SET计算班级平均分
SELECT AVG(score) INTO v_class_avg FROM tb_student;
使用条件判断设置表现等级
IF v_score > v_class_avg THEN
SET v_performance = 'Above Average';
ELSEIF v_score = v_class_avg THEN
SET v_performance = 'Average';
ELSE
SET v_performance = 'Below Average';
END IF;
输出结果
SELECT v_student_name AS '姓名',
v_score AS '分数',
v_class_avg AS '班级平均分',
v_performance AS '表现';
END //
DELIMITER ;
调用存储过程
CALL calculate_student_stats(2);
五、注意事项
1. 作用域规则:内层块可以访问外层块的变量,但外层块不能访问内层块的变量。
2. 变量名冲突:避免变量名与表字段名相同,如果必须相同,可以使用表名限定字段。
3. 错误处理:对于可能返回多行或空行的 `SELECT...INTO`,应该添加异常处理。
4. 性能考虑:变量操作通常在内存中进行,效率较高。
六、用户变量 vs. 局部变量
类型 局部变量 (DECLARE) 用户变量 (@var)
声明方式 DECLARE var_name TYPE SET @var = value
作用域 BEGIN...END 块内 当前会话(连接)
生命周期 块执行期间 会话期间
位置要求 必须在块开头声明 任何地方都可以
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程