MySQL 原生無隨機字串函數,本文提供一個可直接部署的 rand_string(n) 函數,支援指定長度、字元集可擴展,含權限配置與驗證方法。
-- 關鍵:允許建立函數 (主從同步環境必須)
SET GLOBAL log_bin_trust_function_creators = 1;
-- 刪除舊版本
DROP FUNCTION IF EXISTS rand_string;
-- 變更分隔符
DELIMITER $$
CREATE FUNCTION rand_string(n INT)
RETURNS VARCHAR(255)
DETERMINISTIC -- 相同輸入必得相同輸出 (非真隨機,但滿足複製要求)
BEGIN
DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
DECLARE return_str VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
WHILE i < n DO
-- RAND()*62 產生 0-61.999,FLOOR 取整 0-61,+1 對應 SUBSTRING 1-based 索引
SET return_str = CONCAT(return_str, SUBSTRING(chars_str, FLOOR(1 + RAND() * 62), 1));
SET i = i + 1;
END WHILE;
RETURN return_str;
END $$
DELIMITER ;
| 元素 | 說明 |
|---|---|
log_bin_trust_function_creators | 二進位日誌環境下允許建立不確定性函數,主從同步必開 |
DETERMINISTIC | 聲明確定性,滿足 replication 要求 (實際用 RAND() 非確定性,但 MySQL 允許此聲明) |
| 字元集 | 62 個字元 (26小寫+26大寫+10數字),可擴展加入特殊符號 |
FLOOR(1 + RAND() * 62) | 產生 1-62 整數,對應 SUBSTRING 1-based 索引 |
| 最大長度 | 255 字元 (VARCHAR(255)),需更長請修改 RETURNS 類型 |
-- 生成 10 位隨機字串
SELECT rand_string(10);
-- 結果示例: k7Xp9Lm2Qz
-- 批次生成測試資料
INSERT INTO users (username, token)
SELECT CONCAT('user_', id), rand_string(32)
FROM (SELECT 1 AS id UNION SELECT 2 UNION SELECT 3) t;
SHOW FUNCTION STATUS WHERE Db = 'your_database_name';
輸出包含:Name, Type, Definer, Created, Modified, Security_type, Comment, character_set_client, collation_connection, Database Collation。
CREATE FUNCTION rand_string_v2(n INT, charset VARCHAR(255))
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
DECLARE return_str VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
DECLARE len INT DEFAULT CHAR_LENGTH(charset);
IF len = 0 THEN SET charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; END IF;
SET len = CHAR_LENGTH(charset);
WHILE i < n DO
SET return_str = CONCAT(return_str, SUBSTRING(charset, FLOOR(1 + RAND() * len), 1));
SET i = i + 1;
END WHILE;
RETURN return_str;
END
CREATE FUNCTION rand_string_secure(n INT)
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
DECLARE return_str VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
DECLARE bytes BLOB;
WHILE i < n DO
SET bytes = RANDOM_BYTES(1); -- 密碼學安全隨機位元組
SET return_str = CONCAT(return_str, CHAR(ASCII('a') + (ASCII(bytes) % 26))); -- 簡化示例
SET i = i + 1;
END WHILE;
RETURN return_str;
END
DETERMINISTIC 聲明允許主從複製,但實際結果非確定性| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| SQL 函數 (本文) | 純 SQL、可在查詢中用、主從同步 | 效能一般、非加密安全 | 測試資料、簡單 Token |
| 應用層生成 (UUID/Random) | 效能高、加密安全、靈活 | 需應用程式碼部署 | 生產環境 Token、Session ID |
| UUID() | 內建、唯一、標準 | 固定 36 字元、非自定義長度 | 主鍵、唯一標識 |