在使用 OceanBase MySQL 租户开发存储过程、函数或触发器时,你大概率会碰到这样的尴尬:创建语句里明明有分号,但客户端却把它当成了语句的结束符,直接把不完整的代码发给了数据库,然后抛出一堆语法错误。 DELIMITER 就是为解决这个场景而生的。
默认情况下,MySQL 客户端(以及 OBClient)使用 分号(;) 作为 SQL 语句的结束符。当你输入:
SELECT 1; SELECT 2;
客户端会识别到两个语句,分别发送并执行。
但创建一个存储过程时,体内部往往包含多条用分号结尾的语句:
CREATE PROCEDURE sp_test() BEGIN DECLARE a INT DEFAULT 0; SET a = a + 1; SELECT a; END;
如果直接粘贴执行,客户端看到第一个分号就认为语句结束了,于是会把发给服务器,自然报错。
DELIMITER 的作用就是临时通知客户端:“从现在起,不要再用分号作为语句结束符,改用我指定的符号(比如 // 或 $$)。” 这样一来,分号就可以安全地出现在存储过程体内,整个定义作为一个完整的语句提交。
DELIMITER 是 客户端命令,不是 SQL 语句,服务器端完全不认识它。
DELIMITER
用法模板:
DELIMITER // CREATE PROCEDURE ... BEGIN ...; ...; END // DELIMITER ;
三个关键点:
环境说明:本文示例基于 OceanBase 4.x MySQL 租户,客户端为 OBClient 或标准 MySQL 命令行客户端。
-- 切换分隔符为 // DELIMITER // CREATE PROCEDURE calc_bonus(IN emp_id INT, OUT bonus DECIMAL(10,2)) BEGIN DECLARE salary DECIMAL(10,2); SELECT base_salary INTO salary FROM employees WHERE id = emp_id; IF salary > 10000 THEN SET bonus = salary * 0.2; ELSE SET bonus = salary * 0.1; END IF; END // -- 恢复分隔符 DELIMITER ; -- 调用存储过程 CALL calc_bonus(101, @b); SELECT @b;
DELIMITER $$ CREATE FUNCTION get_grade(score INT) RETURNS VARCHAR(10) READS SQL DATA BEGIN DECLARE grade VARCHAR(10); IF score >= 90 THEN SET grade = '优秀'; ELSEIF score >= 75 THEN SET grade = '良好'; ELSEIF score >= 60 THEN SET grade = '及格'; ELSE SET grade = '不及格'; END IF; RETURN grade; END $$ DELIMITER ; -- 使用函数 SELECT get_grade(85);
DELIMITER // CREATE TRIGGER update_log BEFORE UPDATE ON accounts FOR EACH ROW BEGIN INSERT INTO account_logs(account_id, old_amount, new_amount, change_time) VALUES(OLD.id, OLD.amount, NEW.amount, NOW()); END // DELIMITER ;
在一个 SQL 脚本中连续创建多个例程时,只需在开头修改一次分隔符,最后恢复即可:
DELIMITER $$ CREATE PROCEDURE p1() BEGIN ... END$$ CREATE FUNCTION f1() RETURNS INT BEGIN ... END$$ CREATE TRIGGER trg1 ... END$$ DELIMITER ;
每个定义结束都要用新分隔符 ,否则客户端仍会把它们看作一个未完成的语句。
DELIMITER// -- 错误,客户端无法识别 DELIMITER // -- 正确
关键字和分隔符之间 必须至少有一个空格(或 Tab),否则会被当成一个非法命令。
DELIMITER // CREATE PROCEDURE demo() BEGIN SELECT 1; END // -- 此后所有普通语句都需要用 // 结束 SELECT NOW() // -- 如果不小心用了分号,会卡住
一旦忘了 DELIMITER ;,后续的 SELECT、INSERT 等语句只能识别新分隔符。养成在每个定义脚本末尾写上 DELIMITER ; 的好习惯。
DELIMITER // CREATE PROCEDURE wrong() BEGIN DELIMITER ; -- 毫无意义且会破坏客户端解析 SELECT 1; END // DELIMITER ;
DELIMITER是给 客户端看的,不是 SQL 的一部分。写在过程体内不会被执行,反而会扰乱客户端的解析逻辑,甚至导致脚本中断。
DELIMITER 本质上是一个 客户端专用的小工具,它帮你跨越“语句内分号”的陷阱,让完整的 DDL 定义准确无误地提交到数据库。在 OceanBase MySQL 租户下,掌握它只需要记住三点:
如果在操作过程中遇到问题,欢迎在评论区留言交流,后续我们会持续分享更多实战运维干货,记得 关注不迷路 ,下次见~

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70047467/viewspace-3176492/ ,如需转载,请注明出处,否则将追究法律责任。