MySQL DELIMITER 深度解析:為什麼需要、怎麼用、常見坑
DELIMITER 是 MySQL 客戶端指令,非 SQL 標準。它定義「語句結束符號」,讓客戶端知道何時將輸入的多行文字送往 Server 執行。預存程序、觸發器、函數定義包含多個 ;,**必須**暫時變更分隔符。
為什麼需要 DELIMITER?
-- 不改分隔符,直接輸入:
mysql> CREATE FUNCTION shorten(s VARCHAR(255), n INT)
-> RETURNS VARCHAR(255)
-> BEGIN
-> IF ISNULL(s) THEN
-> RETURN ''; -- 這裡的 ; 會被誤判為語句結束!
-> END IF;
-> END;
-- 錯誤:過早執行,語法不完整
正確用法
mysql> DELIMITER // -- 將結束符改為 //
mysql> CREATE FUNCTION shorten(s VARCHAR(255), n INT)
-> RETURNS VARCHAR(255)
-> BEGIN
-> IF ISNULL(s) THEN
-> RETURN ''; -- 這裡的 ; 只是函數體一部分
-> ELSEIF n < 15 THEN
-> RETURN LEFT(s, n);
-> ELSE
-> IF CHAR_LENGTH(s) <= n THEN
-> RETURN s;
-> ELSE
-> RETURN CONCAT(LEFT(s, n-10), '...', RIGHT(s, 5));
-> END IF;
-> END IF;
-> END -- 無分號
-> // -- 這裡的 // 才是真正結束
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ; -- **務必恢復預設分隔符**
常用分隔符選擇
| 分隔符 | 優點 | 缺點 | 適用場景 |
| // | 簡短、不易衝突 | 註釋 // 衝突 | 預存程序/函數/觸發器 |
| $$ | PostgreSQL 風格、不衝突 | 較長 | 複雜程序、遷移專案 |
| ;; | 雙分號 | 極少衝突 | 極少見 |
完整範例:預存程序 + 觸發器 + 函數
預存程序
DELIMITER //
CREATE PROCEDURE simpleproc (OUT param1 INT)
BEGIN
SELECT COUNT(*) INTO param1 FROM t;
END //
DELIMITER ;
CALL simpleproc(@a);
SELECT @a; -- 結果: 3
觸發器
DELIMITER //
CREATE TRIGGER trg_ins BEFORE INSERT ON test
FOR EACH ROW
BEGIN
SET NEW.created_at = NOW();
END //
DELIMITER ;
函數
DELIMITER //
CREATE FUNCTION get_full_name(first VARCHAR(50), last VARCHAR(50))
RETURNS VARCHAR(101)
DETERMINISTIC
BEGIN
RETURN CONCAT(first, ' ', last);
END //
DELIMITER ;
SELECT get_full_name('John', 'Doe'); -- John Doe
客戶端工具差異
| 工具 | DELIMITER 支援 | 備註 |
| mysql CLI | 完整支援 | 標準方式 |
| MySQL Workbench | 腳本區支援 | 執行腳本 (Ctrl+Shift+Enter) 自動處理 |
| Navicat | 物件編輯器 | 無需手寫 DELIMITER,UI 直接編輯 |
| phpMyAdmin | SQL 分頁支援 | 大 SQL 區塊自動識別 |
| DBeaver | 腳本支援 | @set delimiter // 支援 |
| JDBC/應用程式 | **不支援** | 應用層無需 DELIMITER,直接傳完整 SQL 字串 |
常見錯誤與避坑
- 忘記恢復 DELIMITER ;:後續所有指令失效,需重新連線
- 分隔符衝突:程式碼中包含
// 註釋 → 改用 $$
- 應用程式中使用:JDBC/ORM/遷移工具**不需要** DELIMITER,直接傳完整建立語句
DELIMITER **不支援**在預存程序/函數/觸發器內部使用
原理補充
DELIMITER 只影響**客戶端解析器**,不送往 Server
- Server 端只收到完整的
CREATE PROCEDURE ... END 字串
- 資料庫中儲存的程式碼**不包含** DELIMITER
SHOW CREATE PROCEDURE 顯示的定義中無 DELIMITER