首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 存儲過程、函數與觸發器完全指南:語法、示例與最佳實踐

     編輯:MySQL 資料庫相關知識

一、 常用內建函數速查表

1. 字符串函數

函數說明示例
CONCAT(s1,s2...)拼接字符串CONCAT('a','b') → 'ab'
INSTR(str, substr)子串首次出現位置(1-based),無則 0INSTR('abc','b') → 2
LOCATE(substr, str[, pos])同 INSTR,可指定起始位置
SUBSTRING(str, pos[, len])截取子串,**pos 從 1 開始**SUBSTRING('abcd',1,2) → 'ab';pos=0 返回空
LEFT/RIGHT(str, len)左/右側取 len 字符
TRIM([BOTH|LEADING|TRAILING] [pad] FROM str)去除指定字符(默認空格)
REPLACE(str, from, to)替換所有匹配子串
LPAD/RPAD(str, len, pad)左/右填充至指定長度
UCASE/LCASE(str)大/小寫轉換
STRCMP(s1, s2)逐字符比較,返回 -1/0/1
HEX(str/num)字符串轉 ASCII 碼 / 數字轉十六進制HEX('AB') → '4142';HEX(25) → '19'

2. 數學函數

函數說明
ABS(x)絕對值
CEILING/FLOOR(x)向上/向下取整
ROUND(x[, d])四捨五入,d 為小數位;d=0 返回整數,d>0 返回浮點數
MOD(n, m)取餘
POWER(x, y)冪運算
SQRT(x)開平方
RAND([seed])隨機數
SIGN(x)符號:正/負/零 → 1/-1/0
LEAST/MOST(...)最小/最大值
FORMAT(x, d)格式化數字,保留 d 位小數(返回字符串)
CONV(n, from_base, to_base)進制轉換
BIN/HEX/OCT(x)轉二進制/十六進制/八進制字符串

3. 日期時間函數

函數說明
NOW() / CURRENT_TIMESTAMP()當前日期時間
CURDATE() / CURTIME()當前日期 / 時間
DATE(dt) / TIME(dt)提取日期 / 時間部分
DATE_ADD(dt, INTERVAL expr unit)日期加法
DATE_SUB(dt, INTERVAL expr unit)日期減法
DATEDIFF(d1, d2)兩日期相差天數
TIMEDIFF(t1, t2)兩時間差
DATE_FORMAT(dt, fmt)按格式輸出日期
STR_TO_DATE(str, fmt)字符串按格式解析為日期
EXTRACT(unit FROM dt)提取日期指定部分
DAY/DAYOFMONTH/DAYOFWEEK/DAYOFYEAR提取天/周幾/年內第幾天
MONTH/MONTHNAME月份數字/英文名
YEAR/QUARTER/WEEK年/季度/週
HOUR/MINUTE/SECOND/MICROSECOND提取時/分/秒/微秒
LAST_DAY(dt)該月最後一天
MAKEDATE(year, dayofyear)生成日期
MAKETIME(hour, min, sec)生成時間
SEC_TO_TIME(sec) / TIME_TO_SEC(time)秒↔時間互轉
CONVERT_TZ(dt, from_tz, to_tz)時區轉換
ADDTIME(dt, time)加時間間隔

INTERVAL 可用單位:SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR 及組合(DAY_HOUR 等)。

二、 存儲過程

1. 創建與調用

DELIMITER //
DROP PROCEDURE IF EXISTS `PROC_TEST`//
CREATE PROCEDURE `PROC_TEST`(TABLE_NAME VARCHAR(20), NUM INT)
BEGIN
  SET @sql = CONCAT('SELECT * FROM ', TABLE_NAME, ' LIMIT ', NUM);
  PREPARE stmt FROM @sql;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;
END//
DELIMITER ;

-- 調用
CALL PROC_TEST('user', 20);

注意:存儲過程不支持直接用變量作表名,需用動態 SQL(PREPARE/EXECUTE)。

2. 刪除

DROP PROCEDURE IF EXISTS `PROC_TEST`;

三、 觸發器

1. 語法結構

CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON table_name
FOR EACH ROW
trigger_body
  • 同一表同一事件只能有一個觸發器。
  • NEW:INSERT/UPDATE 後的新行;OLD:UPDATE/DELETE 前的舊行。
  • 觸發器體內不能調用返回數據給客戶端的語句(如 SELECT),不能使用顯式/隱式事務控制語句。

2. 實戰示例

場景:tab1 異動同步至 tab2

-- AFTER INSERT
DROP TRIGGER IF EXISTS `t_afterinsert_on_tab1`;
CREATE TRIGGER `t_afterinsert_on_tab1`
AFTER INSERT ON `tab1`
FOR EACH ROW
BEGIN
  INSERT INTO `tab2`(`tab2_id`) VALUES (NEW.`tab1_id`);
END;

-- AFTER DELETE
DROP TRIGGER IF EXISTS `t_afterdelete_on_tab1`;
CREATE TRIGGER `t_afterdelete_on_tab1`
AFTER DELETE ON `tab1`
FOR EACH ROW
BEGIN
  DELETE FROM `tab2` WHERE `tab2_id` = OLD.`tab1_id`;
END;

3. 刪除觸發器

DROP TRIGGER [schema_name.]trigger_name;

四、 進階話題與最佳實踐

1. 存儲過程 vs 應用層邏輯

  • 優點:減少網絡往返、封裝業務邏輯、權限控制細粒度。
  • 缺點:難以版本控制、調試困難、資料庫 CPU 壓力增大、可移植性差。
  • 建議:核心業務邏輯留在應用層,存儲過程僅用於高頻、簡單、數據密集型操作(如批量統計、數據清洗)。

2. 觸發器的隱性風險

  • **隱式邏輯**:應用層代碼無感知,排查問題困難。
  • **性能放大器**:批量操作觸發器逐行執行,嚴重拖慢寫入。
  • **遞歸陷阱**:觸發器中操作同一表再次觸發(需用會話變量標記防重入)。
  • 建議:能不用盡量不用;必須用時,保持極簡、文檔化、加監控。

3. 權限與安全

  • 創建觸發器需 TRIGGER 權限(5.1.6+),存儲過程需 CREATE ROUTINE。
  • 定義者(DEFINER)權限執行,調用者權限需顯式指定 SQL SECURITY INVOKER。

五、 總結

MySQL 存儲過程、函數、觸發器是伺服端編程的三駕馬車。熟練掌握內建函數能寫出簡潔高效的 SQL;存儲過程適用於數據密集型封裝;觸發器是雙刃劍,謹慎使用。原則:業務邏輯上層化,資料庫專注存儲與查詢。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved