CREATE PROCEDURE `shop`.`proc` (OUT param1 INT) BEGIN SELECT COUNT(*) INTO param1 FROM goods; END;
MySQL 存储过程创建代码逐行详解
这是一个非常简洁但信息量很大的 MySQL 存储过程示例。让我从最基础的概念开始,逐行讲清楚。
一、整体功能概述
这个存储过程的作用是:统计 goods 表中的记录总数,并通过输出参数 param1 返回这个数字。
sql
-- 调用示例CALL proc(@count);SELECT @count; -- 显示商品总数
二、逐行详细讲解
第1行:CREATE PROCEDURE
sql
CREATE PROCEDURE `shop`.`proc` (OUT param1 INT)
| 部分 | 含义 |
|---|---|
CREATE PROCEDURE | 创建存储过程的关键字 |
`shop` | 数据库名(使用反引号包裹,避免与关键字冲突) |
. | 点号,表示"的"(shop.proc = shop 数据库中的 proc 存储过程) |
`proc` | 存储过程的名称 |
(OUT param1 INT) | 参数定义:输出参数,类型为整数 |
词源角度
| 单词 | 词源 | 含义 |
|---|---|---|
| CREATE | 拉丁语 creare(制造、产生) | 创建、建立 |
| PROCEDURE | 拉丁语 procedere(向前行进) | 过程、程序 |
| OUT | 古英语 ūt(向外) | 向外、输出 |
三、参数模式详解
OUT 是什么意思?
| 参数模式 | 方向 | 特点 |
|---|---|---|
| IN | 进入过程 | 只能读,不能改(默认) |
| OUT | 离开过程 | 只能写,过程结束时返回 |
| INOUT | 双向 | 既能读,也能写 |
本例中的 OUT param1 INT:
param1只是一个输出通道调用时不需要给它赋值
过程结束后,调用者可以通过这个参数拿到结果
调用对比
sql
-- IN 参数(需要传入值)CALL proc_in(100);-- OUT 参数(传入一个变量,用来接收结果)CALL proc_out(@result);SELECT @result; -- 显示结果
四、第2行:BEGIN
sql
BEGIN
| 单词 | 词源 | 含义 |
|---|---|---|
| BEGIN | 古英语 beginnan | 开始 |
表示存储过程的执行体开始。从这一行到 END 之间的所有代码,就是存储过程要执行的核心逻辑。
五、第3行:核心查询语句
sql
SELECT COUNT(*) INTO param1 FROM goods;
这一行可以拆成三部分理解:
1. SELECT COUNT(*)
| 部分 | 含义 |
|---|---|
SELECT | 查询 |
COUNT(*) | 聚合函数,统计总行数 |
2. INTO param1
这是关键中的关键!
sql
SELECT ... INTO 变量
作用:把查询结果直接存入指定的变量(这里是 param1)。
3. FROM goods
从 goods 表中查询。
没有 INTO 会怎样?
sql
-- ❌ 错误:查询结果没有地方存放SELECT COUNT(*) FROM goods;-- ✅ 正确:结果存入变量SELECT COUNT(*) INTO param1 FROM goods;
六、第4行:END;
sql
END;
| 单词 | 词源 | 含义 |
|---|---|---|
| END | 古英语 endian | 结束、终止 |
表示存储过程的执行体结束。
七、完整执行流程图
text
【创建阶段】 CREATE PROCEDURE proc (OUT param1 INT) ↓ 编译并存储在数据库中 【调用阶段】 CALL proc(@count) ↓ 过程开始执行 ↓ SELECT COUNT(*) INTO param1 FROM goods ↓ 统计 goods 表行数,假设是 100 ↓ 把 100 存入 param1(OUT 参数) ↓ 过程结束,@count 被赋值为 100 ↓ SELECT @count → 输出 100
八、INTO 的其他用法
1. 单列单变量
sql
SELECT COUNT(*) INTO var1 FROM goods;
2. 多列多变量
sql
SELECT name, price INTO var_name, var_price FROM goods WHERE id = 1;
3. 与聚合函数配合
sql
SELECT SUM(price), AVG(price) INTO var_sum, var_avg FROM goods;
九、对比 Oracle 的写法
| 数据库 | 相同点 | 不同点 |
|---|---|---|
| MySQL | SELECT ... INTO | 不需要 AS 或额外声明 |
| Oracle | SELECT ... INTO | 必须写在 BEGIN...END 内 |
十、常见错误及解决
| 错误信息 | 原因 | 解决方法 |
|---|---|---|
PROCEDURE already exists | 存储过程已存在 | 先 DROP PROCEDURE proc 或改用 CREATE OR REPLACE(MySQL 8.0+) |
Unknown database 'shop' | 数据库不存在 | 先 CREATE DATABASE shop |
OUT parameter is not set | 没有给 OUT 参数赋值 | 检查是否有 SELECT ... INTO 或 SET param1 = ... |
十一、与前面 Oracle 例子的关联
对比项 | Oracle 例子(pro_square) | MySQL 例子(proc) |
参数模式 | IN OUT + IN | OUT |
参数作用 | 既输入又输出 | 只输出 |
核心语句 | num := power(...) | SELECT ... INTO |
输出方式 | DBMS_OUTPUT.PUT_LINE | 通过 OUT 参数返回 |
十二、总结
| 代码元素 | 含义 |
|---|---|
CREATE PROCEDURE | 创建存储过程 |
shop.proc | shop 数据库中的 proc 过程 |
OUT param1 INT | 定义一个整数类型的输出参数 |
BEGIN ... END | 执行体边界 |
SELECT COUNT(*) INTO param1 | 查询结果直接存入参数 |
FROM goods | 从商品表查询 |
一句话总结:这个存储过程的作用是——查询 goods 表的总行数,并通过 OUT 参数 param1 返回给调用者。SELECT ... INTO 是 MySQL 中将查询结果直接存入变量的标准写法,而 OUT 参数则是让过程能够把计算结果"传递"出去的通道