👌

MySQLで大量テストデータ作成

2025/01/13に公開

はじめに

「適当にデータを突っ込みたい」、「簡単な負荷テストをしたい」ってときに毎回いろんなサイトを調べてしまうのでまとめた。

テストデータ作成の基本形

数値

-- 0~99の数値
SELECT FLOOR(RAND() * 100);
-- 1~100の数値
SELECT CEIL(RAND() * 100);
-- 5~10の数値
SELECT FLOOR(RAND() * (10 - 5 + 1)) + 5;

文字

-- 10文字の文字列
SELECT SUBSTRING(SHA1(RAND()),1,10);
-- a-zの1文字
SELECT SUBSTRING('abcdefghijklmnopqrstuvwxyz', CEIL(RAND() * 27 ), 1);
-- a-z,A-Z,1-9の1文字
SELECT SUBSTRING('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', CEIL(RAND() * 62 ), 1);

特定の文字

-- spring,summer,fall,winterのどれか(1)
SELECT 
CASE CEIL(RAND() * 4)
    WHEN 1 THEN 'spring'
    WHEN 2 THEN 'summer'
    WHEN 3 THEN 'fall'
    WHEN 4 THEN 'winter'
END;
-- spring,summer,fall,winterのどれか(2)
SELECT ELT(FLOOR(1 + (RAND() * 4)),'spring', 'summer', 'fall', 'winter');

日付

-- 2010/01/01~2020/12/31の間
SELECT DATE_ADD('2010-01-01', INTERVAL FLOOR(RAND() * (DATEDIFF('2020-12-31', '2010-01-01'))) DAY) AS random_date;
-- 2010/01/01~2020/12/31の間(時間込み)
SELECT DATE_ADD('2010-01-01', INTERVAL FLOOR(RAND() * (DATEDIFF('2020-12-31', '2010-01-01'))) DAY) + INTERVAL FLOOR(RAND() * 24) HOUR + INTERVAL FLOOR(RAND() * 60) MINUTE + INTERVAL FLOOR(RAND() * 60) SECOND AS random_datetime;

大量データ登録

テストテーブル作成

-- 部署テーブル
CREATE TABLE departments (
    department_id INT AUTO_INCREMENT PRIMARY KEY,  -- 部署ID
    department_name VARCHAR(100) NOT NULL          -- 部署名
);

-- 社員テーブル
CREATE TABLE employees (
    employee_id INT AUTO_INCREMENT PRIMARY KEY,    -- 社員ID
    name VARCHAR(50) NOT NULL,                     -- 名
    hire_date DATE,                                -- 入社日
    salary DECIMAL(10, 2),                         -- 給与
    department_id INT,                             -- 部署ID
    email VARCHAR(100),                            -- メールアドレス
    phone_number VARCHAR(20),                      -- 電話番号
    FOREIGN KEY (department_id) REFERENCES departments(department_id)
);

1行登録

INSERT INTO employees (
    name,
    hire_date,
    salary,
    email,
    phone_number
) 
SELECT 
    MD5(RAND()),
    DATE_ADD('2010-01-01', INTERVAL FLOOR(RAND() * (DATEDIFF('2020-12-31', '2010-01-01'))) DAY),
    FLOOR(RAND() * (1000000 - 100000 + 1)) + 100000,
    MD5(RAND()),
    CONCAT(ELT(FLOOR(1 + (RAND() * 3)),"070-", "080-", "090-"), LPAD(FLOOR(RAND() * 10000), 4, '0'), '-', LPAD(FLOOR(RAND() * 10000), 4, '0'));

プロシージャで大量登録

部署テーブルと社員テーブルの整合性を保ったままデータを登録

-- ★プロシージャの作成
DELIMITER //
CREATE PROCEDURE insert_data(
    departments_loop_count INT,    -- 部署テーブルへのレコード作成数
    employees_loop_count INT       -- 従業員テーブルへのレコード作成数
)
BEGIN
    DECLARE departments_insert_id INT DEFAULT 0;
    DECLARE departments_num INT DEFAULT 0;
    DECLARE employees_num INT DEFAULT 0;

    -- 部署テーブルへ登録
    WHILE departments_num < departments_loop_count DO
        INSERT INTO departments (
            department_name
        )
        SELECT
            MD5(RAND());
        
        SET departments_num = departments_num + 1;
        SET employees_num = 0;
        -- 部署テーブルへ登録したときのIDを取得
        SET departments_insert_id = LAST_INSERT_ID();

        -- 従業員テーブルへ登録
        WHILE employees_num < employees_loop_count DO
            INSERT INTO employees (
                name,
                hire_date,
                salary,
                department_id,
                email,
                phone_number
            ) 
            SELECT 
                MD5(RAND()),
                DATE_ADD('2010-01-01', INTERVAL FLOOR(RAND() * (DATEDIFF('2020-12-31', '2010-01-01'))) DAY),
                FLOOR(RAND() * (1000000 - 100000 + 1)) + 100000,
                departments_insert_id,
                MD5(RAND()),
                CONCAT(ELT(FLOOR(1 + (RAND() * 3)),"070-", "080-", "090-"), LPAD(FLOOR(RAND() * 10000), 4, '0'), '-', LPAD(FLOOR(RAND() * 10000), 4, '0'));
            
            SET employees_num = employees_num + 1;
        END WHILE;
    END WHILE;
END //
DELIMITER ;

-- ★プロシージャ実行(5部署登録で1部署につき10人従業員登録)
CALL insert_data (5, 10);

Discussion