需求:向表插入 100 條測試數據,姓名從字符池隨機組合(2-3 字),年齡 20-50 區間隨機,**且相鄰兩行姓名+年齡不完全相同**。MySQL RAND() 配合存儲過程輕鬆實現。
RAND():返回 0~1 間浮點數,每次調用值不同。RAND(N):指定種子 N,**同一查詢中多次調用返回固定序列**;不同查詢間序列相同。SELECT RAND(), RAND(5); -- 第1次: 0.7946..., 0.4061... -- 第2次: 0.1291..., 0.4061... -- RAND(5) 固定,RAND() 變化 -- 第3次: 0.2615..., 0.4061...
DELIMITER $$
CREATE PROCEDURE `pro3`(num INT)
BEGIN
DECLARE fname CHAR(1); -- 姓氏
DECLARE name1 CHAR(1); -- 名字第1字
DECLARE name2 CHAR(1); -- 名字第2字(可選)
DECLARE fullname VARCHAR(3); -- 完整姓名
DECLARE pre_fullname VARCHAR(3) DEFAULT ''; -- 上一行姓名
DECLARE age INT; -- 年齡
DECLARE i INT DEFAULT 1; -- 計數器
WHILE i <= num DO
-- 1. 隨機姓氏(8 個常用姓)
SET fname = SUBSTRING('趙錢孫李周吳鄭王', FLOOR(1 + 8 * RAND()), 1);
-- 2. 隨機名字字符(14 個備選字)
SET name1 = SUBSTRING('一二三四五六七八九十甲乙丙丁', ROUND(1 + 14 * RAND()), 1);
SET name2 = SUBSTRING('一二三四五六七八九十甲乙丙丁', ROUND(1 + 14 * RAND()), 1);
-- 3. 隨機決定 2 字或 3 字姓名
IF ROUND(RAND()) = 0 THEN
SET fullname = CONCAT(fname, name1);
ELSE
SET fullname = CONCAT(fname, name1, name2);
END IF;
-- 4. 隨機年齡 20-50
SET age = FLOOR(20 + 31 * RAND());
-- 5. 獲取上一行姓名(避免連續重複)
SELECT `name` INTO pre_fullname FROM user1 ORDER BY id DESC LIMIT 1;
-- 6. 去重邏輯:若與上一行相同則跳過本次循環(i 不增),否則插入並 i+1
IF fullname = pre_fullname AND i > 1 THEN
SET i = i; -- 什麼都不做,繼續下一次循環重新隨機
ELSEIF fullname IS NULL THEN
SET i = i; -- 防御性判斷
ELSE
INSERT INTO user1 VALUES (NULL, fullname, age);
SET i = i + 1;
END IF;
END WHILE;
END$$
DELIMITER ;
TRUNCATE TABLE user1; CALL pro3(100); SELECT * FROM user1;
輸出 100 行,**無任意相鄰兩行姓名+年齡完全相同**。示例片段:
+-----+-----------+-----+ | id | name | age | +-----+-----------+-----+ | 1 | 吳甲九 | 32 | | 2 | 趙丙 | 49 | | 3 | 錢二 | 40 | | 4 | 鄭二丙 | 34 | | ... | ... | ... | | 100 | 吳十四 | 29 | +-----+-----------+-----+
| 技術點 | 實現方式 | 說明 |
|---|---|---|
| 隨機整數區間 [a,b] | FLOOR(a + (b-a+1)*RAND()) | 年齡 20-50:FLOOR(20+31*RAND()) |
| 字符池隨機取字 | SUBSTRING(str, pos, 1) + FLOOR/ROUND | 姓氏池 8 字、名字池 14 字 |
| 變長姓名 (2/3 字) | IF ROUND(RAND())=0 THEN 2字 ELSE 3字 | 50% 概率各半 |
| 相鄰去重 | 查詢上一行 ORDER BY id DESC LIMIT 1 比較 | 相同則不計數重試 |
| 循環控制 | WHILE i <= num + 手動 i = i+1 | 去重時 i 不增,保證最終行數 |
INSERT ... VALUES (...),(...),... 或 LOAD DATA。UNIQUE KEY uk_name_age (name, age),捕獲 Duplicate entry 異常重試。RAND(seed) 初始化,後續 RAND() 序列確定。MySQL RAND() + 存儲過程可實現**帶約束的隨機測試數據生成**;核心在於 FLOOR(a+(b-a+1)*RAND()) 區間取整、字符池 SUBSTRING 取字、**相鄰去重邏輯控制循環計數器**。生產級大數據建議應用層生成,資料庫只負責高效導入。