MySQL 生成隨機數字、字符串、日期、驗證碼及 UUID的方法
上一篇介紹瞭如何在 Oracle 生成隨機數字、字符串、日期、驗證碼以及 UUID,今天我們繼續討論在 MySQL 中生成各種隨機數據的方法。
📝計算機生成的都是偽隨機數,並不是真正的物理隨機數。
生成隨機數字
生成 0 到 1 之間的隨機數
MySQL 中的 RAND 函數可以用於生成一個大於等於 0 小於 1 的隨機數字。例如:
SELECT rand(); rand() | ------------------| 0.7245639057127423| SELECT rand(); rand() | -------------------| 0.01697599982561171|
該函數返回的數據類型為 double,包含 16 位小數;每次調用都會返回不同的數據。
如果想要重現某些場景,需要確保每次運行時生成相同的隨機數。這種情況下可以為 RAND 函數傳遞一個輸入參數,設置一個隨機數種子。例如:
SELECT rand(1); rand(1) | -------------------| 0.40540353712197724| SELECT rand(1); rand(1) | -------------------| 0.40540353712197724|
從結果可以看出,相同的種子返回瞭相同的隨機數。
生成指定范圍內的隨機數
基於 RAND 函數和數學運算,可以返回任意兩個數字之間的隨機數:
low + RAND() * (high − low)
以上表達式將會返回一個大於等於 low,小於 high 的隨機數。例如:
SELECT 10 + rand(1) * 10; 10 + rand(1) * 10 | ------------------| 14.054035371219772|
以上示例返回瞭一個大於等於 10 且小於 20 的隨機數字。
如果想要生成某個范圍內的隨機整數,可以加上 FLOOR 函數。例如:
SELECT floor(10 + rand(1) * (10)) AS rd; rd | ----| 14.0|
該語句返回瞭一個大於等於 10,小於等於 19(不是 20)的隨機整數。
生成 6 位數字手機驗證碼
我們已經獲得瞭指定范圍內的隨機整數,加上 LPAD 函數就可以生成由 6 位數字字符組成的手機驗證碼。例如:
SELECT lpad(floor(rand(999) * 1000000), 6, '0') AS captcha; captcha| -------| 088146 |
其中,lpad 函數可以確保數據不夠 6 位時在前面補足 0。
生成遵循正態分佈的隨機數
RAND 函數生成的是一個遵循均勻分佈的隨機數,MySQL 沒有提供生成遵循正態分佈(normal distribution)的隨機數。我們可以創建一個存儲函數來模擬正態分佈的隨機數:
delimiter // create function normal_distrib(mean double, stdev double) returns double no sql begin set @x = rand(), @y = rand(); set @nd = (sqrt(-2 * log(@x)) * cos(2 * pi() * @y)) * stdev + mean; return @nd; end // delimiter ;
以上函數利用 Box-Muller 變換算法通過兩個平均分佈的隨機數生成正態分佈的隨機數。
以下語句通過 normal_distrib 函數生成瞭一個期望值為 0,標準差為 1 的正態分佈隨機數:
SELECT normal_distrib(0,1); normal_distrib(0,1)| -------------------| 1.4930564399841173|
以下語句可以用於驗證 normal_distrib 函數是否遵循正態分佈:
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 次,計算這些數據的平均值和標準差,返回結果非常接近 0 和 1。
生成隨機字符串
生成固定長度的隨機字符串
除瞭隨機數字之外,有時候我們也需要生成一些隨機的字符串。MySQL 沒有提供專門生成隨機字符串的函數,但是可以通過其他函數進行模擬。例如:
SELECT char(floor(rand() * 26)+65) as rand_char; rand_char| ---------| T |
以上查詢返回瞭一個隨機的大寫字母,char 函數用於將 ASCII 碼轉換為對應的字符。我們可以基於該查詢進一步創建一個存儲函數:
delimiter // create function rand_string(len integer) returns text no sql begin 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 函數可以返回由任意可打印字符(ASCII 碼從 33 到 126)組成的隨機字符串。例如:
rand_string(8)| --------------| 7j5dz[58 |
以上示例返回瞭一個長度為 8,由可打印字符組成的隨機字符串。
另外,MySQL 中的 elt 函數也可以用於返回指定位置中的元素。例如:
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 |
以上語句返回瞭一個隨機的數字或者大寫字母,將其替換到 rand_string 函數可以返回一個由數字和大寫字母組成的隨機字符串。
生成可變長度的隨機字符串
那麼,怎麼返回一個長度可變的隨機字符串呢?很簡單,為 rand_string 函數指定一個隨機的長度參數即可。例如:
SELECT rand_string(floor(10 + rand() * 11)); rand_string(floor(10 + rand() * 11))| ------------------------------------| 4U13MjO+($}k"cO@5%[ |
以上示例返回瞭一個長度大於等於 10 且小於等於 20,由可打印字符組成的隨機字符串。
生成隨機日期和時間
將指定日期增加一個隨機的數字,就可以得到隨機的日期。例如:
SELECT date_add('2020-01-01', interval rand() * 31 day) rand_date; rand_date | ----------| 2020-01-19|
以上示例返回瞭 2020 年 1 月中的某個隨機日期。以下語句則返回瞭一天中的某個隨機時間:
SELECT sec_to_time(rand() * 3600) rand_time; rand_time | ------------------| 00:05:29.546878000|
其中,sec_to_time 函數用於將秒數轉換為時間數據。
獲取表中的隨機記錄
對於返回多行數據的查詢語句,RAND 函數每次都會返回不同的隨機數據。例如:
SELECT rand(1) FROM employee; rand(1) | --------------------| 0.40540353712197724| 0.8716141803857071| 0.1418603212962489| ...
利用這個特性,我們可以從表中返回隨機的數據行。例如:
SELECT emp_id,emp_name FROM employee ORDER BY rand(1) LIMIT 5; emp_id|emp_name | ------|----------| 6|魏延 | 14|張苞 | 16|周倉 | 15|趙統 | 1|劉備 |
以上示例從 employee 表中返回瞭 5 行隨機記錄。該方法需要為表中的每行數據都生成一個隨機數,然後進行排序;所以會隨著表中的數據量增加而逐漸變慢。
如果表中存在自增主鍵,也可以基於主鍵生成一個隨機數據。例如:
SELECT round(rand() * (SELECT max(emp_id) FROM employee)) AS id; id | ----| 10.0|
然後基於這個隨機數返回一條隨機的記錄:
SELECT e.emp_id, e.emp_name FROM employee e INNER JOIN (SELECT round(rand() * (SELECT max(emp_id) FROM employee)) AS id ) AS t WHERE e.emp_id >= t.id LIMIT 1; emp_id|emp_name| ------|--------| 9|趙雲 |
這種方法一次隻能返回一條隨機記錄,而且隻有當自增字段的值沒有間隙時才會返回均勻分佈的隨機記錄。
生成 UUID
UUID(Universal Unique Identifier)或者 GUID(Globally Unique Identifier)是一個 128 比特的數字,可以用於唯一標識每個網絡對象或資源。由於它的生成機制,一個 UUID 可以保證幾乎不會與其他 UUID 重復,因此常常用於生成數據庫中的主鍵值。
MySQL 提供瞭一個系統函數 UUID,可以用於生成 UUID。例如:
SELECT uuid(); uuid() | ------------------------------------| 35f67fde-e0e9-11ea-9d25-0800272142b1|
如果想要生成沒有中劃線(-)的 UUID,可以使用 REPLACE 函數:
SELECT replace(uuid(),'-',''); replace(uuid(),'-','') | --------------------------------| 8505290be0ea11ea9d250800272142b1|
除此之外,MySQL 還提供瞭一個UUID_SHORT 函數,它可以返回一個 64 比特的無符號整數。例如:
SELECT uuid_short(); uuid_short() | -----------------| 98862025337208832|
該函數返回的是一個“短的”唯一標識符,隻有滿足以下條件時才具有唯一性:
- 當前服務器的 server_id 位於 0 到 255 之間,並且在復制結構中具有唯一性;
- 重啟 mysqld 前後沒有將服務器主機的系統時間往回調整;
- 每秒鐘的平均調用次數少於 1600 萬次。
總結
本文介紹瞭在 MySQL 數據庫中生成隨機數據的方法,包括隨機數字、驗證碼、隨機字符串以及隨機日期和時間等,同時還介紹瞭如何從表中返回隨機記錄,以及如何生成 UUID。
到此這篇關於MySQL 生成隨機數字、字符串、日期、驗證碼及 UUID的方法的文章就介紹到這瞭,更多相關MySQL 生成隨機數字 UUID內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Oracle生成隨機數字、字符串、日期、驗證碼及 UUID的方法
- postgreSQL自動生成隨機數值的實例
- MySQL數據庫之內置函數和自定義函數 function
- 使用 SQL 語句實現一個年會抽獎程序的代碼
- mysql自動插入百萬模擬數據的操作代碼