MySQL 生成隨機(jī)數(shù)字、字符串、日期、驗證碼及 UUID的方法
上一篇介紹了如何在 Oracle 生成隨機(jī)數(shù)字、字符串、日期、驗證碼以及 UUID,今天我們繼續(xù)討論在 MySQL 中生成各種隨機(jī)數(shù)據(jù)的方法。
📝計算機(jī)生成的都是偽隨機(jī)數(shù),并不是真正的物理隨機(jī)數(shù)。
生成隨機(jī)數(shù)字生成 0 到 1 之間的隨機(jī)數(shù)MySQL 中的 RAND 函數(shù)可以用于生成一個大于等于 0 小于 1 的隨機(jī)數(shù)字。例如:
SELECT rand();rand() |------------------|0.7245639057127423|SELECT rand();rand() |-------------------|0.01697599982561171|
該函數(shù)返回的數(shù)據(jù)類型為 double,包含 16 位小數(shù);每次調(diào)用都會返回不同的數(shù)據(jù)。
如果想要重現(xiàn)某些場景,需要確保每次運行時生成相同的隨機(jī)數(shù)。這種情況下可以為 RAND 函數(shù)傳遞一個輸入?yún)?shù),設(shè)置一個隨機(jī)數(shù)種子。例如:
SELECT rand(1);rand(1) |-------------------|0.40540353712197724|SELECT rand(1);rand(1) |-------------------|0.40540353712197724|
從結(jié)果可以看出,相同的種子返回了相同的隨機(jī)數(shù)。
生成指定范圍內(nèi)的隨機(jī)數(shù)基于 RAND 函數(shù)和數(shù)學(xué)運算,可以返回任意兩個數(shù)字之間的隨機(jī)數(shù):
low + RAND() * (high − low)
以上表達(dá)式將會返回一個大于等于 low,小于 high 的隨機(jī)數(shù)。例如:
SELECT 10 + rand(1) * 10;10 + rand(1) * 10 |------------------|14.054035371219772|
以上示例返回了一個大于等于 10 且小于 20 的隨機(jī)數(shù)字。
如果想要生成某個范圍內(nèi)的隨機(jī)整數(shù),可以加上 FLOOR 函數(shù)。例如:
SELECT floor(10 + rand(1) * (10)) AS rd;rd |----|14.0|
該語句返回了一個大于等于 10,小于等于 19(不是 20)的隨機(jī)整數(shù)。
生成 6 位數(shù)字手機(jī)驗證碼我們已經(jīng)獲得了指定范圍內(nèi)的隨機(jī)整數(shù),加上 LPAD 函數(shù)就可以生成由 6 位數(shù)字字符組成的手機(jī)驗證碼。例如:
SELECT lpad(floor(rand(999) * 1000000), 6, ’0’) AS captcha;captcha|-------|088146 |
其中,lpad 函數(shù)可以確保數(shù)據(jù)不夠 6 位時在前面補(bǔ)足 0。
生成遵循正態(tài)分布的隨機(jī)數(shù)RAND 函數(shù)生成的是一個遵循均勻分布的隨機(jī)數(shù),MySQL 沒有提供生成遵循正態(tài)分布(normal distribution)的隨機(jī)數(shù)。我們可以創(chuàng)建一個存儲函數(shù)來模擬正態(tài)分布的隨機(jī)數(shù):
delimiter //create function normal_distrib(mean double, stdev double) returns double no sqlbeginset @x = rand(), @y = rand();set @nd = (sqrt(-2 * log(@x)) * cos(2 * pi() * @y)) * stdev + mean;return @nd;end//delimiter ;
以上函數(shù)利用 Box-Muller 變換算法通過兩個平均分布的隨機(jī)數(shù)生成正態(tài)分布的隨機(jī)數(shù)。
以下語句通過 normal_distrib 函數(shù)生成了一個期望值為 0,標(biāo)準(zhǔn)差為 1 的正態(tài)分布隨機(jī)數(shù):
SELECT normal_distrib(0,1);normal_distrib(0,1)|-------------------| 1.4930564399841173|
以下語句可以用于驗證 normal_distrib 函數(shù)是否遵循正態(tài)分布:
with recursive temp(val) as ( select normal_distrib(0,1) union all select normal_distrib(0,1) from temp limit 1000000)select /*+ set_var(cte_max_recursion_depth = 1m) */avg(val),std(val)from temp;avg(val) |std(val) |---------------------|------------------|-0.002340136192616743|0.9994844557755181|
通過運行 1000000 次,計算這些數(shù)據(jù)的平均值和標(biāo)準(zhǔn)差,返回結(jié)果非常接近 0 和 1。
生成隨機(jī)字符串生成固定長度的隨機(jī)字符串除了隨機(jī)數(shù)字之外,有時候我們也需要生成一些隨機(jī)的字符串。MySQL 沒有提供專門生成隨機(jī)字符串的函數(shù),但是可以通過其他函數(shù)進(jìn)行模擬。例如:
SELECT char(floor(rand() * 26)+65) as rand_char;rand_char|---------|T |
以上查詢返回了一個隨機(jī)的大寫字母,char 函數(shù)用于將 ASCII 碼轉(zhuǎn)換為對應(yīng)的字符。我們可以基于該查詢進(jìn)一步創(chuàng)建一個存儲函數(shù):
delimiter //create function rand_string(len integer) returns text no sqlbegin declare counter int default 1; declare str text default ’’; if len < 1 then return null; end if; while counter <= len do set str = concat(str, char(floor(rand() * 94) + 33)); set counter = counter + 1; end while; return str;end//delimiter ;
rand_string 函數(shù)可以返回由任意可打印字符(ASCII 碼從 33 到 126)組成的隨機(jī)字符串。例如:
rand_string(8)|--------------|7j5dz[58 |
以上示例返回了一個長度為 8,由可打印字符組成的隨機(jī)字符串。
另外,MySQL 中的 elt 函數(shù)也可以用于返回指定位置中的元素。例如:
SELECT elt(1 + floor(rand() * 36), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ’A’,’B’,’C’,’D’,’E’,’F’,’G’, ’H’,’I’,’J’,’K’,’L’,’M’,’N’, ’O’,’P’,’Q’,’R’,’S’,’T’, ’U’,’V’,’W’,’X’,’Y’,’Z’) as val;val|---|B |
以上語句返回了一個隨機(jī)的數(shù)字或者大寫字母,將其替換到 rand_string 函數(shù)可以返回一個由數(shù)字和大寫字母組成的隨機(jī)字符串。
生成可變長度的隨機(jī)字符串那么,怎么返回一個長度可變的隨機(jī)字符串呢?很簡單,為 rand_string 函數(shù)指定一個隨機(jī)的長度參數(shù)即可。例如:
SELECT rand_string(floor(10 + rand() * 11));rand_string(floor(10 + rand() * 11))|------------------------------------|4U13MjO+($}k'cO@5%[ |
以上示例返回了一個長度大于等于 10 且小于等于 20,由可打印字符組成的隨機(jī)字符串。
生成隨機(jī)日期和時間將指定日期增加一個隨機(jī)的數(shù)字,就可以得到隨機(jī)的日期。例如:
SELECT date_add(’2020-01-01’, interval rand() * 31 day) rand_date;rand_date |----------|2020-01-19|
以上示例返回了 2020 年 1 月中的某個隨機(jī)日期。以下語句則返回了一天中的某個隨機(jī)時間:
SELECT sec_to_time(rand() * 3600) rand_time;rand_time |------------------|00:05:29.546878000|
其中,sec_to_time 函數(shù)用于將秒數(shù)轉(zhuǎn)換為時間數(shù)據(jù)。
獲取表中的隨機(jī)記錄對于返回多行數(shù)據(jù)的查詢語句,RAND 函數(shù)每次都會返回不同的隨機(jī)數(shù)據(jù)。例如:
SELECT rand(1) FROM employee;rand(1) |--------------------| 0.40540353712197724| 0.8716141803857071| 0.1418603212962489|...
利用這個特性,我們可以從表中返回隨機(jī)的數(shù)據(jù)行。例如:
SELECT emp_id,emp_nameFROM employeeORDER BY rand(1)LIMIT 5;emp_id|emp_name |------|----------| 6|魏延 | 14|張苞 | 16|周倉 | 15|趙統(tǒng) | 1|劉備 |
以上示例從 employee 表中返回了 5 行隨機(jī)記錄。該方法需要為表中的每行數(shù)據(jù)都生成一個隨機(jī)數(shù),然后進(jìn)行排序;所以會隨著表中的數(shù)據(jù)量增加而逐漸變慢。
如果表中存在自增主鍵,也可以基于主鍵生成一個隨機(jī)數(shù)據(jù)。例如:
SELECT round(rand() * (SELECT max(emp_id) FROM employee)) AS id;id |----|10.0|
然后基于這個隨機(jī)數(shù)返回一條隨機(jī)的記錄:
SELECT e.emp_id, e.emp_nameFROM employee eINNER JOIN (SELECT round(rand() * (SELECT max(emp_id) FROM employee)) AS id ) AS tWHERE e.emp_id >= t.idLIMIT 1;emp_id|emp_name|------|--------| 9|趙云 |
這種方法一次只能返回一條隨機(jī)記錄,而且只有當(dāng)自增字段的值沒有間隙時才會返回均勻分布的隨機(jī)記錄。
生成 UUIDUUID(Universal Unique Identifier)或者 GUID(Globally Unique Identifier)是一個 128 比特的數(shù)字,可以用于唯一標(biāo)識每個網(wǎng)絡(luò)對象或資源。由于它的生成機(jī)制,一個 UUID 可以保證幾乎不會與其他 UUID 重復(fù),因此常常用于生成數(shù)據(jù)庫中的主鍵值。
MySQL 提供了一個系統(tǒng)函數(shù) UUID,可以用于生成 UUID。例如:
SELECT uuid();uuid()|------------------------------------|35f67fde-e0e9-11ea-9d25-0800272142b1|
如果想要生成沒有中劃線(-)的 UUID,可以使用 REPLACE 函數(shù):
SELECT replace(uuid(),’-’,’’);replace(uuid(),’-’,’’) |--------------------------------|8505290be0ea11ea9d250800272142b1|
除此之外,MySQL 還提供了一個UUID_SHORT 函數(shù),它可以返回一個 64 比特的無符號整數(shù)。例如:
SELECT uuid_short();uuid_short() |-----------------|98862025337208832|
該函數(shù)返回的是一個“短的”唯一標(biāo)識符,只有滿足以下條件時才具有唯一性:
當(dāng)前服務(wù)器的 server_id 位于 0 到 255 之間,并且在復(fù)制結(jié)構(gòu)中具有唯一性; 重啟 mysqld 前后沒有將服務(wù)器主機(jī)的系統(tǒng)時間往回調(diào)整; 每秒鐘的平均調(diào)用次數(shù)少于 1600 萬次。總結(jié)本文介紹了在 MySQL 數(shù)據(jù)庫中生成隨機(jī)數(shù)據(jù)的方法,包括隨機(jī)數(shù)字、驗證碼、隨機(jī)字符串以及隨機(jī)日期和時間等,同時還介紹了如何從表中返回隨機(jī)記錄,以及如何生成 UUID。
到此這篇關(guān)于MySQL 生成隨機(jī)數(shù)字、字符串、日期、驗證碼及 UUID的方法的文章就介紹到這了,更多相關(guān)MySQL 生成隨機(jī)數(shù)字 UUID內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. MySQL InnoDB 鎖的相關(guān)總結(jié)2. 學(xué)好Oracle的六條總結(jié)3. 簡單了解mysql語句書寫和執(zhí)行順序4. Mysql入門系列:MYSQL客戶機(jī)程序2—增加錯誤檢查5. MySQL中InnoDB和MyISAM類型的差別6. Mysql入門系列:建立MYSQL客戶機(jī)程序的一般過程7. DB2 與 Microsoft SQL Server 2000 之間的 SQL 數(shù)據(jù)復(fù)制8. MySql遠(yuǎn)程連接的實現(xiàn)方法9. mysql的like模式10. Windows下在DOS用mysql命令行導(dǎo)入.sql文件
