需求:主表 triggletest_triggle 狀態更新時,自動寫入歷史表 triggletest。建立 AFTER UPDATE 觸發器卻報語法錯誤,最終發現是 客戶端工具 (HeidiSQL) 分隔符處理問題。
-- 主表
CREATE TABLE `triggletest_triggle` (
`id` INT(11) NOT NULL,
`name` VARCHAR(5) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
-- 歷史表
CREATE TABLE `triggletest` (
`seq` INT(11) NOT NULL AUTO_INCREMENT,
`id` INT(11) NOT NULL,
`name` VARCHAR(5) NULL DEFAULT NULL,
PRIMARY KEY (`seq`),
INDEX `idx_id` (`id`)
) ENGINE=InnoDB;
-- 測試資料
INSERT INTO `triggletest_triggle` VALUES (1, 'A');
DROP TRIGGER IF EXISTS test1;
CREATE TRIGGER test1 AFTER UPDATE ON triggletest_triggle
FOR EACH ROW
BEGIN
INSERT INTO triggletest(id) VALUES (NEW.id);
END
報錯:
/* SQL Error (1064): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE TRIGGER test1 AFTER UPDATE ON triggletest_triggle FOR EACH ROW BEGIN' at line 2 */
BEGIN ... END 區塊,內部有分號 ;。CREATE TRIGGER 在第一個分號處被截斷,語法不完整。DELIMITER $$
DROP TRIGGER IF EXISTS test1;
CREATE TRIGGER test1
AFTER UPDATE ON triggletest_triggle
FOR EACH ROW
BEGIN
INSERT INTO triggletest(id, name) VALUES (NEW.id, NEW.name);
END$$
DELIMITER ;
# 更新主表 UPDATE triggletest_triggle SET name='B' WHERE id=1; # 查詢歷史表 SELECT * FROM triggletest; +-----+----+------+ | seq | id | name | +-----+----+------+ | 1 | 1 | B | +-----+----+------+
| 工具 | 是否需手動 DELIMITER | 備註 |
|---|---|---|
MySQL 官方 CLI (mysql) | 是 | 標準做法 |
| MySQL Workbench | 否 | 內建解析器自動識別 BEGIN/END 區塊 |
| HeidiSQL | 是 | 需在查詢分頁工具列選擇「不分割語句」或手動加 DELIMITER |
| Navicat | 否 | 支援「執行選取區塊」完整送入 |
| DBeaver | 否 | 智慧分割,可識別觸發器/程序 |
| DataGrip | 否 | 語法感知執行 |
.sql 檔,部署時用 mysql -u root -p < trigger.sql 執行,避免 GUI 工具干擾。trg_{table}_{timing}_{event},如 trg_triggletest_triggle_au_ins_hist。SHOW TRIGGERS\G 或查詢 information_schema.TRIGGERS。TRIGGER 權限 (MySQL 5.1.6+)。log_bin_trust_function_creators 相關)。「工具不會背鍋,但開發者要懂工具的限制。」—— 記一次因分隔符導致的 30 分鐘排查。