CALL proc(),大批量 SQL 不走網路。GRANT EXECUTE 控制存取,隱藏表結構與業務邏輯。DELIMITER //
CREATE PROCEDURE `proc_name`(
IN p_in INT,
OUT p_out VARCHAR(100),
INOUT p_io DATE
)
BEGIN
-- 宣告區
DECLARE v_cnt INT DEFAULT 0;
DECLARE v_name VARCHAR(50);
-- 邏輯區
SELECT COUNT(*) INTO v_cnt FROM users WHERE id = p_in;
IF v_cnt > 0 THEN
SELECT name INTO v_name FROM users WHERE id = p_in;
SET p_out = v_name;
ELSE
SET p_out = 'NOT_FOUND';
END IF;
SET p_io = DATE_ADD(p_io, INTERVAL 1 DAY);
END//
DELIMITER ;
DELIMITER // 避免分號提前結束定義,結尾 DELIMITER ; 恢復。IN(預設)、OUT、INOUT。DECLARE var TYPE [DEFAULT val]; 必須在 BEGIN 後、首條 SQL 前。SET var = expr; 或 SELECT col INTO var FROM ...-- 調用
SET @p_in = 1; SET @p_io = CURDATE();
CALL proc_name(@p_in, @p_out, @p_io);
SELECT @p_out, @p_io;
-- 查看定義
SHOW CREATE PROCEDURE proc_name;
-- 列出庫內所有過程
SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = 'mydb';
-- 狀態
SHOW PROCEDURE STATUS WHERE Db = 'mydb';
IF condition THEN ... ELSEIF ... ELSE ... END IF;
CASE var
WHEN 1 THEN ...
WHEN 2 THEN ...
ELSE ...
END CASE;
-- WHILE:先判斷
WHILE v < 10 DO ... END WHILE;
-- REPEAT:後判斷(至少執行一次)
REPEAT ... UNTIL v >= 10 END REPEAT;
-- LOOP:無條件,配合 LEAVE/ITERATE
my_loop: LOOP
IF v = 3 THEN SET v = v + 1; ITERATE my_loop; END IF;
IF v >= 10 THEN LEAVE my_loop; END IF;
...
END LOOP;
DECLARE cur CURSOR FOR SELECT id, name FROM users WHERE status = 1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur;
read_loop: LOOP
FETCH cur INTO v_id, v_name;
IF done THEN LEAVE read_loop; END IF;
-- 處理邏輯
END LOOP;
CLOSE cur;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
INSERT INTO error_log(msg) VALUES ('SQL Exception in proc_name');
ROLLBACK;
END;
DECLARE CONTINUE HANDLER FOR SQLWARNING
BEGIN
INSERT INTO warn_log(msg) VALUES (CONCAT('Warning: ', @@warning_count));
END;
| 類型 | 行為 |
|---|---|
EXIT | 發生錯誤**離開當前 BEGIN...END 區塊** |
CONTINUE | 發生錯誤**繼續執行後續語句** |
條件值:SQLSTATE、SQLWARNING、NOT FOUND、SQLEXCEPTION、MySQL 錯誤碼。
| 分類 | 函數 | 說明 |
|---|---|---|
| 字符串 | CONCAT(s1, s2...) | 拼接 |
SUBSTRING(str, pos, len) | 截取(pos 從 1 開始) | |
REPLACE(str, from, to) | 替換所有匹配 | |
TRIM([BOTH|LEADING|TRAILING] rem FROM str) | 去除字符 | |
INSTR(str, substr) | 首次出現位置 | |
UCASE/LCASE | 大小寫轉換 | |
HEX/UNHEX | 十六進制互轉 | |
| 數學 | ROUND(n, d) | 四捨五入保留 d 位 |
FLOOR/CEIL | 向下/向上取整 | |
MOD(n, m) | 取餘 | |
POWER(n, p) | 冪運算 | |
RAND([seed]) | 隨機數 | |
| 日期時間 | NOW()/CURRENT_TIMESTAMP | 當前日期時間 |
DATE_ADD(d, INTERVAL n UNIT) | 日期加減 | |
DATEDIFF(d1, d2) | 天數差 | |
DATE_FORMAT(d, fmt) | 格式化輸出 | |
STR_TO_DATE(str, fmt) | 字符串轉日期 | |
DAYNAME/DAYOFWEEK | 星期名/數字 | |
LAST_DAY(d) | 月份最後一天 |
DELIMITER //
CREATE FUNCTION `fn_greet`(p_name VARCHAR(50)) RETURNS VARCHAR(100)
DETERMINISTIC
BEGIN
RETURN CONCAT('Hello, ', p_name, '!');
END//
DELIMITER ;
SELECT fn_greet('World'); -- Hello, World!
函數必須 RETURNS 類型,體內至少一條 RETURN。
ALTER PROCEDURE proc_name [characteristic ...];
DROP PROCEDURE IF EXISTS proc_name;