大数跨境

OceanBase MySQL 租户 DELIMITER 用法详解

OceanBase MySQL 租户 DELIMITER 用法详解 瑞蓝创软件
2026-07-17
2
导读:OB MySQL 租户 DELIMITER 使用指南
图片

作者简介黄开祥瑞蓝创数据库工程师















原创内容未经授权不得随意使用,转载请联系小编并注明来源


在使用 OceanBase MySQL 租户开发存储过程、函数或触发器时,你大概率会碰到这样的尴尬:创建语句里明明有分号,但客户端却把它当成了语句的结束符,直接把不完整的代码发给了数据库,然后抛出一堆语法错误。DELIMITER 就是为解决这个场景而生的。

1. 为什么需要 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 语句,服务器端完全不认识它。

2. 基本语法

DELIMITER 
  • 可以是任意字符序列,常见的有 //、$$、;;
  • 执行 DELIMITER ;可以将分隔符恢复为默认的分号。

用法模板:

DELIMITER //

CREATE PROCEDURE ... 
BEGIN
  ...;
  ...;
END //

DELIMITER ;

三个关键点:

  1. 先改分隔符在创建对象之前执行DELIMITER
  2. 用新分隔符结束定义:在之后用新分隔符(如 //)标记整个语句结束。
  3. 恢复分隔符:定义完成后务必执行DELIMITER ;,否则后续普通 SQL 都会因缺少分号而“卡住”。

3. OceanBase MySQL 租户实战案例

环境说明:本文示例基于 OceanBase 4.x MySQL 租户,客户端为 OBClient 或标准 MySQL 命令行客户端。

3.1 创建存储过程

-- 切换分隔符为 //
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;

3.2 创建函数

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);

3.3 创建触发器

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 ;

3.4 批量定义多个对象

在一个 SQL 脚本中连续创建多个例程时,只需在开头修改一次分隔符,最后恢复即可:

DELIMITER $$

CREATE PROCEDURE p1() BEGIN ... END$$

CREATE FUNCTION f1() RETURNS INT BEGIN ... END$$

CREATE TRIGGER trg1 ... END$$

DELIMITER ;

每个定义结束都要用新分隔符 ,否则客户端仍会把它们看作一个未完成的语句。

4. 常见错误 & 避坑指南

坑 1:DELIMITER 后忘记空格

DELIMITER//        --  错误,客户端无法识别
DELIMITER //       --  正确

关键字和分隔符之间必须至少有一个空格(或 Tab),否则会被当成一个非法命令。

坑 2:忘记恢复分隔符为

DELIMITER //

CREATE PROCEDURE demo() BEGIN SELECT 1; END //
-- 此后所有普通语句都需要用 // 结束
SELECT NOW() //   -- 如果不小心用了分号,会卡住

一旦忘了 DELIMITER ;,后续的 SELECT、INSERT    等语句只能识别新分隔符。养成在每个定义脚本末尾写上 DELIMITER ; 的好习惯。

坑 3:在存储过程体内包含 DELIMITER 命令

DELIMITER //
CREATE PROCEDURE wrong() 
BEGIN
  DELIMITER ;        --  毫无意义且会破坏客户端解析
  SELECT 1;
END //
DELIMITER ;

DELIMITER是给客户端看的,不是 SQL 的一部分。写在过程体内不会被执行,反而会扰乱客户端的解析逻辑,甚至导致脚本中断。

5. OceanBase 特别说明

  • OceanBase MySQL 租户完全兼容 MySQL 5.7/8.0 的存储过程、函数、触发器语法,因此 DELIMITER 的用法与标准 MySQL 一模一样。
  • OceanBase 的 MySQL 模式 PL 引擎在处理复杂逻辑时性能优异,结合 DELIMITER 可以轻松创建包含多条控制流语句的例程。
  • 如果在 OBClient 中执行一个包含 DELIMITER 的 SQL 文件( source file.sql ),OBClient 会逐行解析并识别分隔符切换,与原生 mysql 客户端行为一致。

6. 总结

DELIMITER 本质上是一个客户端专用的小工具,它帮你跨越“语句内分号”的陷阱,让完整的 DDL 定义准确无误地提交到数据库。在 OceanBase MySQL 租户下,掌握它只需要记住三点:

  1. 先在 OBClient 中用 DELIMITER 改成非分号符号(如 // );
  2. 用新符号结束每个定义
  3. 最后恢复分号


如果在操作过程中遇到问题,欢迎在评论区留言交流,后续我们会持续分享更多实战运维干货,记得关注不迷路,下次见~

END


瑞蓝创 OceanBase OBCP V4 精英训练营

点击下方图片立即了解详情

瑞蓝创02.png


··


·

·

▼ 点击「阅读原文」,了解更多产品技术文章


【声明】内容源于网络
0
0
瑞蓝创软件
专注于企业信息科技战略咨询、数据中心规划及运维、智能化软件产品研发,致力于为金融、能源、电信、制造等行业提供智能的业务永续及流程自动化解决方案。
内容 58
粉丝 0
瑞蓝创软件 专注于企业信息科技战略咨询、数据中心规划及运维、智能化软件产品研发,致力于为金融、能源、电信、制造等行业提供智能的业务永续及流程自动化解决方案。
总阅读510
粉丝0
内容58