千家信息网

MySQL 用随机数据填充外键表

发表于:2025-01-20 作者:千家信息网编辑
千家信息网最后更新 2025年01月20日,参考:http://blog.itpub.net/29254281/viewspace-1686302/准备环境1.创建数字辅助表create table nums(id int not null p
千家信息网最后更新 2025年01月20日MySQL 用随机数据填充外键表参考:
http://blog.itpub.net/29254281/viewspace-1686302/

准备环境
1.创建数字辅助表
create table nums(id int not null primary key);

delimiter $$
create procedure pFastCreateNums(cnt int)
begin
declare s int default 1;
truncate table nums;
insert into nums select s;
while s*2<=cnt do
insert into nums select id+s from nums;
set s=s*2;
end while;
end $$
delimiter ;


call pFastCreateNums(1000000);

数字辅助表的行数决定最后能生成的表行数的最大值.

2.创建生成随机字符的函数

  1. DROP FUNCTION IF EXISTS rand_string;
  2. delimiter //
  3. CREATE FUNCTION rand_string(l_num int UNSIGNED,l_type tinyint UNSIGNED)
  4. RETURNS varchar(2000)
  5. BEGIN
  6. -- Function : rand_string
  7. -- Author : dbachina#dbachina.com
  8. -- Date : 2010/5/30
  9. -- l_num : The length of random string
  10. -- l_type: The string type
  11. -- 1.0-9
  12. -- 2.a-z
  13. -- 3.A-Z
  14. -- 4.a-zA-Z
  15. -- 5.0-9a-zA-Z
  16. -- :
  17. -- mysql> select rand_string(12,5) random_string;
  18. -- +---------------+
  19. -- | random_string |
  20. -- +---------------+
  21. -- | 3KzGJCUJUplw |
  22. -- +---------------+
  23. -- 1 row in set (0.00 sec)
  24. DECLARE i int UNSIGNED DEFAULT 0;
  25. DECLARE v_chars varchar(64) DEFAULT '0123456789';
  26. DECLARE result varchar (2000) DEFAULT '';

  27. IF l_type = 1 THEN
  28. SET v_chars = '0123456789';
  29. ELSEIF l_type = 2 THEN
  30. SET v_chars = 'abcdefghijklmnopqrstuvwxyz';
  31. ELSEIF l_type = 3 THEN
  32. SET v_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  33. ELSEIF l_type = 4 THEN
  34. SET v_chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  35. ELSEIF l_type = 5 THEN
  36. SET v_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  37. ELSE
  38. SET v_chars = '0123456789';
  39. END IF;

  40. WHILE i < l_num DO
  41. SET result = concat( result,substr(v_chars,ceil(rand()*(length(v_chars)-1)),1) );
  42. SET i = i + 1;
  43. END WHILE;
  44. RETURN result;
  45. END;
  46. //
  47. delimiter ;



准备实验表.
先创建一些带有外键约束的表.数据库名称是 probe

  1. CREATE TABLE `t_jvm_info` (
  2. `id` bigint(20) NOT NULL AUTO_INCREMENT,
  3. `app_name` varchar(32) NOT NULL COMMENT '应用名称',
  4. `host_name` varchar(32) NOT NULL COMMENT '主机名称',
  5. `collect_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '采集时间',
  6. `version` varchar(32) NOT NULL DEFAULT '' COMMENT 'jvm版本',
  7. `vendor` varchar(32) NOT NULL DEFAULT '' COMMENT '厂商',
  8. `java_home` varchar(64) NOT NULL DEFAULT '' COMMENT '客户端javahome路径',
  9. `loaded_class_count` int(11) NOT NULL DEFAULT '-1' COMMENT '已经加载的类数量',
  10. `unloaded_class_count` int(11) NOT NULL DEFAULT '-1' COMMENT '已经卸载的类数量',
  11. `total_loaded_class_count` int(11) NOT NULL DEFAULT '-1' COMMENT '累计加载的类数量',
  12. `heap_init` float NOT NULL DEFAULT '-1' COMMENT '堆内存初始大小',
  13. `heap_committed` bigint(20) NOT NULL DEFAULT '-1' COMMENT 'os分配给jvm的堆内存',
  14. `heap_max` bigint(20) NOT NULL DEFAULT '-1' COMMENT '堆内存上限',
  15. `heap_used` bigint(20) NOT NULL DEFAULT '-1' COMMENT '已经使用的堆内存大小',
  16. `non_heap_init` bigint(20) NOT NULL DEFAULT '-1' COMMENT '非堆内存初始大小',
  17. `non_heap_committed` bigint(20) NOT NULL DEFAULT '-1' COMMENT 'os分配给jvm的非堆内存',
  18. `non_heap_max` bigint(20) NOT NULL DEFAULT '-1' COMMENT '非堆内存上限',
  19. `non_heap_used` bigint(20) NOT NULL DEFAULT '-1' COMMENT '已经使用的非堆内存大小',
  20. `current_thread_count` int(11) NOT NULL DEFAULT '-1' COMMENT '当前jvm线程总数',
  21. `total_started_thread_count` int(11) NOT NULL DEFAULT '-1' COMMENT '累计启动过的线程总数',
  22. `peak_thread_count` int(11) NOT NULL DEFAULT '-1' COMMENT '线程数量最大值',
  23. `daemon_thread_count` int(11) NOT NULL DEFAULT '-1' COMMENT 'daemon线程数量',
  24. PRIMARY KEY (`id`),
  25. KEY `app_name` (`app_name`,`host_name`,`collect_time`),
  26. KEY `host_name` (`host_name`,`collect_time`)
  27. ) ENGINE=InnoDB AUTO_INCREMENT=2001 DEFAULT CHARSET=utf8mb4 COMMENT='jvm采集信息表';

  28. CREATE TABLE `t_jvm_gc_info` (
  29. `id` bigint(20) NOT NULL AUTO_INCREMENT,
  30. `t_jvm_info_id` bigint(20) NOT NULL COMMENT 'jvm采集信息表id',
  31. `name` varchar(32) NOT NULL COMMENT 'gc类型名称',
  32. `gctime` bigint(20) NOT NULL DEFAULT '-1' COMMENT 'gc时间',
  33. `gccount` bigint(20) NOT NULL DEFAULT '-1' COMMENT 'gc次数',
  34. PRIMARY KEY (`id`),
  35. KEY `t_jvm_info_id` (`t_jvm_info_id`),
  36. CONSTRAINT `t_jvm_gc_info_ibfk_1` FOREIGN KEY (`t_jvm_info_id`) REFERENCES `t_jvm_info` (`id`)
  37. ) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8mb4 COMMENT='jvm gc采集信息表';

创建可以自动生成数据的存储过程


  1. drop procedure if exists auto_fill ;
  2. delimiter $$
  3. create procedure auto_fill(pDb varchar(32),pTableList varchar(1024))
  4. begin
  5. declare done int default 0;
  6. declare v_dbName varchar(128);
  7. declare v_fullTableName varchar(128);
  8. declare v_tableName varchar(128);
  9. declare v_rowCount int;
  10. declare cur_test CURSOR for select dbName,fullTableName,tableName,rowCount from tmp_table_info;
  11. DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

  12. -- 临时表,用于保存拆分参数之后的结果.主要信息就是数据库名称和表名称
  13. drop table if exists tmp_table_info;
  14. create temporary table tmp_table_info
  15. select pDb dbName,
  16. concat(pDb,'.',substring_index ( value_str,',',1 )) fullTableName ,
  17. substring_index ( value_str,',',1 ) tableName,
  18. substring_index ( value_str,',',-1 ) rowCount
  19. from (
  20. select substring_index(substring_index(pTableList,';',b.id),';',-1) value_str
  21. from
  22. nums b
  23. where b.id <= (length(pTableList) - length(replace(pTableList,';',''))+1)
  24. ) t1;

  25. -- 禁用外键
  26. SET FOREIGN_KEY_CHECKS=0;
  27. open cur_test;
  28. repeat
  29. fetch cur_test into v_dbName,v_fullTableName,v_tableName,v_rowCount;
  30. if done!=1 then

  31. set @sql=concat('insert ignore into ',v_dbName,'.',v_tableName,' select ');
  32. select
  33. @sql:=concat(@sql,
  34. case
  35. when extra='auto_increment' then concat('id,')
  36. when data_type='int' then if(rowCount is null,'round(rand()*2147483647),',concat('round(rand()*',rowCount,'),'))
  37. when data_type='bigint' then if(rowCount is null,'round(rand()*9223372036854775807),',concat('round(rand()*',rowCount,'),'))
  38. when data_type='smallint' then 'round(rand()*32767),'
  39. when data_type='tinyint' then 'round(rand()*127 ),'
  40. when data_type='varchar' then concat('rand_string(',CHARACTER_MAXIMUM_LENGTH,',5),')
  41. when data_type='date' then 'now()-interval round(90*rand()) day,'
  42. when data_type='datetime' then 'now()-interval round(90*rand()) day,'
  43. when data_type='timestamp' then 'now()-interval round(90*rand()) day,'
  44. when data_type in('double','float') then 'round(rand()*32767,5),'
  45. when data_type like '%text%' then concat('rand_string(2048,5),')
  46. end
  47. ) s
  48. from (
  49. select
  50. k.referenced_table_name,
  51. k.referenced_column_name,
  52. c.table_schema,
  53. c.table_name,
  54. c.column_name,
  55. c.data_type,
  56. c.CHARACTER_MAXIMUM_LENGTH,
  57. c.extra,
  58. t.rowCount
  59. from information_schema.columns c
  60. left join information_schema.KEY_COLUMN_USAGE k on(
  61. c.table_schema=k.table_schema and
  62. c.table_name=k.table_name and
  63. c.column_name=k.column_name and
  64. k.constraint_name
  65. in (select constraint_name from information_schema.REFERENTIAL_CONSTRAINTS)
  66. )
  67. left join tmp_table_info t on(t.dbName=k.table_schema and t.tableName=k.table_name)
  68. where (c.table_schema,c.table_name) =(v_dbName,v_tableName)
  69. order by c.ORDINAL_POSITION
  70. ) t2
  71. ;
  72. set @sql=left(@sql,char_length(@sql)-1);
  73. select nullif ('please stand by...',@sql:=concat(@sql,' from nums where id<=',v_rowCount,';')) info;
  74. prepare statement from @sql;
  75. execute statement;
  76. commit;
  77. end if;
  78. until done end repeat;
  79. close cur_test;

  80. -- 恢复外键
  81. SET FOREIGN_KEY_CHECKS=1;


  82. end ;
  83. $$
  84. delimiter ;

执行存储过程填充数据

call auto_fill('probe','t_jvm_gc_info,100000;t_jvm_info,2000');

过程第一个参数是 数据库名称
第二个参数是 表名和行数的字符串列表.

测试数据生成自行删除外键约束即可


0