一、场景描述

线上有一台MySQL服务器,里面有几十个数据库,每个库有N多表。

现在需要将每个表的信息,统计到excel中,格式如下:

库名 表名 表说明 建表语句
db1 users 用户表 CREATE TABLE `users` (...)

二、需求分析

怎么做呢?

1. 手动录入(太TM苦逼了,那么多表呀...)

2. 使用Python自动录入(Great)

三、获取相关信息

需要利用的技术点,有2个。一个是pymysql(连接mysql),一个是xlwt(写入excel)

安装模块

  1. pip3 install pymysql xlwt

获取所有数据库

请确保有一个账号,能够远程连接MySQL,并且有对应的权限。

我用的是本机的MySQL,目前只有一个数据库db1

新建文件tj.py,内容如下:

  1. import pymysql
  2.  
  3. conn = pymysql.connect(
  4. host="127.0.0.1", # mysql ip地址
  5. user="root",
  6. passwd="",
  7. port=3306 # mysql 端口号,注意:必须是int类型
  8. )
  9.  
  10. cur = conn.cursor() # 创建游标
  11.  
  12. # 获取mysql中所有数据库
  13. cur.execute('SHOW DATABASES')
  14.  
  15. data_all = cur.fetchall() # 获取执行的返回结果
  16. print(data_all)

执行输出:

  1. (('information_schema',), ('db1',), ('mysql',), ('performance_schema',), ('sys',))

结果是一个元组,里面的每一个元素也是元组。使用for循环

  1. import pymysql
  2.  
  3. conn = pymysql.connect(
  4. host="127.0.0.1", # mysql ip地址
  5. user="root",
  6. passwd="",
  7. port=3306 # mysql 端口号,注意:必须是int类型
  8. )
  9.  
  10. cur = conn.cursor() # 创建游标
  11.  
  12. # 获取mysql中所有数据库
  13. cur.execute('SHOW DATABASES')
  14.  
  15. data_all = cur.fetchall() # 获取执行的返回结果
  16. # print(data_all)
  17.  
  18. for i in data_all:
  19. print(i[0]) # 获取库名

执行输出:

  1. information_schema
  2. db1
  3. mysql
  4. performance_schema
  5. sys

获取所有的表

要获取所有的表,必须要切换到对应的数据库中,使用show tables 才可以获取。

  1. import pymysql
  2.  
  3. conn = pymysql.connect(
  4. host="127.0.0.1", # mysql ip地址
  5. user="root",
  6. passwd="",
  7. port=3306 # mysql 端口号,注意:必须是int类型
  8. )
  9.  
  10. cur = conn.cursor() # 创建游标
  11.  
  12. # 获取mysql中所有数据库
  13. cur.execute('SHOW DATABASES')
  14.  
  15. data_all = cur.fetchall() # 获取执行的返回结果
  16. # print(data_all)
  17.  
  18. for i in data_all:
  19. conn.select_db(i[0]) # 切换到指定的库中
  20. cur.execute('SHOW TABLES') # 查看库中所有的表
  21. ret = cur.fetchall() # 获取执行结果
  22. print(ret)

执行输出:

  1. (('CHARACTER_SETS',), ('COLLATIONS',), ('COLLATION_CHARACTER_SET_APPLICABILITY',), ('COLUMNS',), ('COLUMN_PRIVILEGES',), ('ENGINES',), ('EVENTS',), ('FILES',), ('GLOBAL_STATUS',), ('GLOBAL_VARIABLES',), ('KEY_COLUMN_USAGE',), ('OPTIMIZER_TRACE',), ('PARAMETERS',), ('PARTITIONS',), ('PLUGINS',), ('PROCESSLIST',), ('PROFILING',), ('REFERENTIAL_CONSTRAINTS',), ('ROUTINES',), ('SCHEMATA',), ('SCHEMA_PRIVILEGES',), ('SESSION_STATUS',), ('SESSION_VARIABLES',), ('STATISTICS',), ('TABLES',), ('TABLESPACES',), ('TABLE_CONSTRAINTS',), ('TABLE_PRIVILEGES',), ('TRIGGERS',), ('USER_PRIVILEGES',), ('VIEWS',), ('INNODB_LOCKS',), ('INNODB_TRX',), ('INNODB_SYS_DATAFILES',), ('INNODB_FT_CONFIG',), ('INNODB_SYS_VIRTUAL',), ('INNODB_CMP',), ('INNODB_FT_BEING_DELETED',), ('INNODB_CMP_RESET',), ('INNODB_CMP_PER_INDEX',), ('INNODB_CMPMEM_RESET',), ('INNODB_FT_DELETED',), ('INNODB_BUFFER_PAGE_LRU',), ('INNODB_LOCK_WAITS',), ('INNODB_TEMP_TABLE_INFO',), ('INNODB_SYS_INDEXES',), ('INNODB_SYS_TABLES',), ('INNODB_SYS_FIELDS',), ('INNODB_CMP_PER_INDEX_RESET',), ('INNODB_BUFFER_PAGE',), ('INNODB_FT_DEFAULT_STOPWORD',), ('INNODB_FT_INDEX_TABLE',), ('INNODB_FT_INDEX_CACHE',), ('INNODB_SYS_TABLESPACES',), ('INNODB_METRICS',), ('INNODB_SYS_FOREIGN_COLS',), ('INNODB_CMPMEM',), ('INNODB_BUFFER_POOL_STATS',), ('INNODB_SYS_COLUMNS',), ('INNODB_SYS_FOREIGN',), ('INNODB_SYS_TABLESTATS',))
  2. (('school',), ('users',))
  3. (('columns_priv',), ('db',), ('engine_cost',), ('event',), ('func',), ('general_log',), ('gtid_executed',), ('help_category',), ('help_keyword',), ('help_relation',), ('help_topic',), ('innodb_index_stats',), ('innodb_table_stats',), ('ndb_binlog_index',), ('plugin',), ('proc',), ('procs_priv',), ('proxies_priv',), ('server_cost',), ('servers',), ('slave_master_info',), ('slave_relay_log_info',), ('slave_worker_info',), ('slow_log',), ('tables_priv',), ('time_zone',), ('time_zone_leap_second',), ('time_zone_name',), ('time_zone_transition',), ('time_zone_transition_type',), ('user',))
  4. (('accounts',), ('cond_instances',), ('events_stages_current',), ('events_stages_history',), ('events_stages_history_long',), ('events_stages_summary_by_account_by_event_name',), ('events_stages_summary_by_host_by_event_name',), ('events_stages_summary_by_thread_by_event_name',), ('events_stages_summary_by_user_by_event_name',), ('events_stages_summary_global_by_event_name',), ('events_statements_current',), ('events_statements_history',), ('events_statements_history_long',), ('events_statements_summary_by_account_by_event_name',), ('events_statements_summary_by_digest',), ('events_statements_summary_by_host_by_event_name',), ('events_statements_summary_by_program',), ('events_statements_summary_by_thread_by_event_name',), ('events_statements_summary_by_user_by_event_name',), ('events_statements_summary_global_by_event_name',), ('events_transactions_current',), ('events_transactions_history',), ('events_transactions_history_long',), ('events_transactions_summary_by_account_by_event_name',), ('events_transactions_summary_by_host_by_event_name',), ('events_transactions_summary_by_thread_by_event_name',), ('events_transactions_summary_by_user_by_event_name',), ('events_transactions_summary_global_by_event_name',), ('events_waits_current',), ('events_waits_history',), ('events_waits_history_long',), ('events_waits_summary_by_account_by_event_name',), ('events_waits_summary_by_host_by_event_name',), ('events_waits_summary_by_instance',), ('events_waits_summary_by_thread_by_event_name',), ('events_waits_summary_by_user_by_event_name',), ('events_waits_summary_global_by_event_name',), ('file_instances',), ('file_summary_by_event_name',), ('file_summary_by_instance',), ('global_status',), ('global_variables',), ('host_cache',), ('hosts',), ('memory_summary_by_account_by_event_name',), ('memory_summary_by_host_by_event_name',), ('memory_summary_by_thread_by_event_name',), ('memory_summary_by_user_by_event_name',), ('memory_summary_global_by_event_name',), ('metadata_locks',), ('mutex_instances',), ('objects_summary_global_by_type',), ('performance_timers',), ('prepared_statements_instances',), ('replication_applier_configuration',), ('replication_applier_status',), ('replication_applier_status_by_coordinator',), ('replication_applier_status_by_worker',), ('replication_connection_configuration',), ('replication_connection_status',), ('replication_group_member_stats',), ('replication_group_members',), ('rwlock_instances',), ('session_account_connect_attrs',), ('session_connect_attrs',), ('session_status',), ('session_variables',), ('setup_actors',), ('setup_consumers',), ('setup_instruments',), ('setup_objects',), ('setup_timers',), ('socket_instances',), ('socket_summary_by_event_name',), ('socket_summary_by_instance',), ('status_by_account',), ('status_by_host',), ('status_by_thread',), ('status_by_user',), ('table_handles',), ('table_io_waits_summary_by_index_usage',), ('table_io_waits_summary_by_table',), ('table_lock_waits_summary_by_table',), ('threads',), ('user_variables_by_thread',), ('users',), ('variables_by_thread',))
  5. (('host_summary',), ('host_summary_by_file_io',), ('host_summary_by_file_io_type',), ('host_summary_by_stages',), ('host_summary_by_statement_latency',), ('host_summary_by_statement_type',), ('innodb_buffer_stats_by_schema',), ('innodb_buffer_stats_by_table',), ('innodb_lock_waits',), ('io_by_thread_by_latency',), ('io_global_by_file_by_bytes',), ('io_global_by_file_by_latency',), ('io_global_by_wait_by_bytes',), ('io_global_by_wait_by_latency',), ('latest_file_io',), ('memory_by_host_by_current_bytes',), ('memory_by_thread_by_current_bytes',), ('memory_by_user_by_current_bytes',), ('memory_global_by_current_bytes',), ('memory_global_total',), ('metrics',), ('processlist',), ('ps_check_lost_instrumentation',), ('schema_auto_increment_columns',), ('schema_index_statistics',), ('schema_object_overview',), ('schema_redundant_indexes',), ('schema_table_lock_waits',), ('schema_table_statistics',), ('schema_table_statistics_with_buffer',), ('schema_tables_with_full_table_scans',), ('schema_unused_indexes',), ('session',), ('session_ssl_status',), ('statement_analysis',), ('statements_with_errors_or_warnings',), ('statements_with_full_table_scans',), ('statements_with_runtimes_in_95th_percentile',), ('statements_with_sorting',), ('statements_with_temp_tables',), ('sys_config',), ('user_summary',), ('user_summary_by_file_io',), ('user_summary_by_file_io_type',), ('user_summary_by_stages',), ('user_summary_by_statement_latency',), ('user_summary_by_statement_type',), ('version',), ('wait_classes_global_by_avg_latency',), ('wait_classes_global_by_latency',), ('waits_by_host_by_latency',), ('waits_by_user_by_latency',), ('waits_global_by_latency',), ('x$host_summary',), ('x$host_summary_by_file_io',), ('x$host_summary_by_file_io_type',), ('x$host_summary_by_stages',), ('x$host_summary_by_statement_latency',), ('x$host_summary_by_statement_type',), ('x$innodb_buffer_stats_by_schema',), ('x$innodb_buffer_stats_by_table',), ('x$innodb_lock_waits',), ('x$io_by_thread_by_latency',), ('x$io_global_by_file_by_bytes',), ('x$io_global_by_file_by_latency',), ('x$io_global_by_wait_by_bytes',), ('x$io_global_by_wait_by_latency',), ('x$latest_file_io',), ('x$memory_by_host_by_current_bytes',), ('x$memory_by_thread_by_current_bytes',), ('x$memory_by_user_by_current_bytes',), ('x$memory_global_by_current_bytes',), ('x$memory_global_total',), ('x$processlist',), ('x$ps_digest_95th_percentile_by_avg_us',), ('x$ps_digest_avg_latency_distribution',), ('x$ps_schema_table_statistics_io',), ('x$schema_flattened_keys',), ('x$schema_index_statistics',), ('x$schema_table_lock_waits',), ('x$schema_table_statistics',), ('x$schema_table_statistics_with_buffer',), ('x$schema_tables_with_full_table_scans',), ('x$session',), ('x$statement_analysis',), ('x$statements_with_errors_or_warnings',), ('x$statements_with_full_table_scans',), ('x$statements_with_runtimes_in_95th_percentile',), ('x$statements_with_sorting',), ('x$statements_with_temp_tables',), ('x$user_summary',), ('x$user_summary_by_file_io',), ('x$user_summary_by_file_io_type',), ('x$user_summary_by_stages',), ('x$user_summary_by_statement_latency',), ('x$user_summary_by_statement_type',), ('x$wait_classes_global_by_avg_latency',), ('x$wait_classes_global_by_latency',), ('x$waits_by_host_by_latency',), ('x$waits_by_user_by_latency',), ('x$waits_global_by_latency',))

结果也是一个大的元组,使用for循环,提取表名

  1. import pymysql
  2.  
  3. conn = pymysql.connect(
  4. host="127.0.0.1", # mysql ip地址
  5. user="root",
  6. passwd="",
  7. port=3306 # mysql 端口号,注意:必须是int类型
  8. )
  9.  
  10. cur = conn.cursor() # 创建游标
  11.  
  12. # 获取mysql中所有数据库
  13. cur.execute('SHOW DATABASES')
  14.  
  15. data_all = cur.fetchall() # 获取执行的返回结果
  16. # print(data_all)
  17.  
  18. for i in data_all:
  19. conn.select_db(i[0]) # 切换到指定的库中
  20. cur.execute('SHOW TABLES') # 查看库中所有的表
  21. ret = cur.fetchall() # 获取执行结果
  22.  
  23. for j in ret:
  24. print(j[0]) # 获取每一个表名

执行输出:

  1. CHARACTER_SETS
  2. COLLATIONS
  3. COLLATION_CHARACTER_SET_APPLICABILITY
  4. COLUMNS
  5. ...

获取建表语句

使用命令 show create table 表名 获取

  1. import pymysql
  2.  
  3. conn = pymysql.connect(
  4. host="127.0.0.1", # mysql ip地址
  5. user="root",
  6. passwd="",
  7. port=3306 # mysql 端口号,注意:必须是int类型
  8. )
  9.  
  10. cur = conn.cursor() # 创建游标
  11.  
  12. # 获取mysql中所有数据库
  13. cur.execute('SHOW DATABASES')
  14.  
  15. data_all = cur.fetchall() # 获取执行的返回结果
  16. # print(data_all)
  17.  
  18. for i in data_all:
  19. conn.select_db(i[0]) # 切换到指定的库中
  20. cur.execute('SHOW TABLES') # 查看库中所有的表
  21. ret = cur.fetchall() # 获取执行结果
  22.  
  23. for j in ret:
  24. # 获取每一个表的建表语句
  25. cur.execute('show create table `%s`;' % j[0])
  26. ret = cur.fetchall()
  27. print(ret)

执行输出:

  1. (('CHARACTER_SETS', "CREATE TEMPORARY TABLE `CHARACTER_SETS` (\n `CHARACTER_SET_NAME` varchar(32) NOT NULL DEFAULT '',\n `DEFAULT_COLLATE_NAME` varchar(32) NOT NULL DEFAULT '',\n `DESCRIPTION` varchar(60) NOT NULL DEFAULT '',\n `MAXLEN` bigint(3) NOT NULL DEFAULT '0'\n) ENGINE=MEMORY DEFAULT CHARSET=utf8"),)
  2. ...

从结果中可以看出,建表语句中有大量的 \n  这个是换行符。注意:是\n后面还有2个空格

领导肯定是不想看到有这种符号存在,怎么去除呢?使用eval+replace

  1. import pymysql
  2.  
  3. conn = pymysql.connect(
  4. host="127.0.0.1", # mysql ip地址
  5. user="root",
  6. passwd="",
  7. port=3306 # mysql 端口号,注意:必须是int类型
  8. )
  9.  
  10. cur = conn.cursor() # 创建游标
  11.  
  12. # 获取mysql中所有数据库
  13. cur.execute('SHOW DATABASES')
  14.  
  15. data_all = cur.fetchall() # 获取执行的返回结果
  16. # print(data_all)
  17.  
  18. for i in data_all:
  19. conn.select_db(i[0]) # 切换到指定的库中
  20. cur.execute('SHOW TABLES') # 查看库中所有的表
  21. ret = cur.fetchall() # 获取执行结果
  22.  
  23. for j in ret:
  24. # 获取每一个表的建表语句
  25. cur.execute('show create table `%s`;' % j[0])
  26. ret = cur.fetchall()
  27. # print(ret)
  28. for k in ret:
  29. # 替换反斜杠,使用\\。替换换行符\n,使用下面的
  30. structure = eval(repr(k[1]).replace('\\n ', ''))
  31. print(structure)

执行输出:

  1. CREATE TEMPORARY TABLE `CHARACTER_SETS` (`CHARACTER_SET_NAME` varchar(32) NOT NULL DEFAULT '',`DEFAULT_COLLATE_NAME` varchar(32) NOT NULL DEFAULT '',`DESCRIPTION` varchar(60) NOT NULL DEFAULT '',`MAXLEN` bigint(3) NOT NULL DEFAULT ''
  2. ) ENGINE=MEMORY DEFAULT CHARSET=utf8
  3. ...

发现结果正常了!

结果真的很多,但我都需要吗?no no no,其实我只需要db1而已,其他的都是系统自带的表,我并不关心!

排除多余的表

定义一个排序列表,使用if排除,注意:i[0] 是库名

  1. import pymysql
  2.  
  3. conn = pymysql.connect(
  4. host="127.0.0.1", # mysql ip地址
  5. user="root",
  6. passwd="",
  7. port=3306 # mysql 端口号,注意:必须是int类型
  8. )
  9.  
  10. cur = conn.cursor() # 创建游标
  11.  
  12. # 获取mysql中所有数据库
  13. cur.execute('SHOW DATABASES')
  14.  
  15. data_all = cur.fetchall() # 获取执行的返回结果
  16. # print(data_all)
  17.  
  18. for i in data_all:
  19. # 排序列表,排除mysql自带的数据库
  20. exclude_list = ["sys", "information_schema", "mysql", "performance_schema"]
  21. if i[0] not in exclude_list: # 判断不在列表中时
  22. conn.select_db(i[0]) # 切换到指定的库中
  23. cur.execute('SHOW TABLES') # 查看库中所有的表
  24. ret = cur.fetchall() # 获取执行结果
  25.  
  26. for j in ret:
  27. # 获取每一个表的建表语句
  28. cur.execute('show create table `%s`;' % j[0])
  29. ret = cur.fetchall()
  30. # print(ret)
  31. for k in ret:
  32. # 替换反斜杠,使用\\。替换换行符\n,使用下面的
  33. structure = eval(repr(k[1]).replace('\\n ', ''))
  34. print(structure)

执行输出:

  1. CREATE TABLE `school` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,PRIMARY KEY (`id`)
  2. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  3. CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '姓名',PRIMARY KEY (`id`),KEY `ix_users_name` (`name`)
  4. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表'

获取表说明

看下面一条建表语句

  1. CREATE TABLE `users` (
  2. `id` int(11) NOT NULL AUTO_INCREMENT,
  3. `name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '姓名',
  4. PRIMARY KEY (`id`),
  5. KEY `ix_users_name` (`name`)
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';

我需要获取 用户表 这3个字,如何操作?

1. 使用正则匹配?Oh, I'm sorry ,本人正则水平太烂了...

2. 使用COMMENT切割?那可不行,name字段也有COMMENT。

仔细发现,可以看出这2个COMMENT还是有区别的。最后一个COMMENT,后面有一个等号。

OK,那么就可以通过COMMENT=来切割了。

  1. import pymysql
  2.  
  3. conn = pymysql.connect(
  4. host="127.0.0.1", # mysql ip地址
  5. user="root",
  6. passwd="",
  7. port=3306 # mysql 端口号,注意:必须是int类型
  8. )
  9.  
  10. cur = conn.cursor() # 创建游标
  11.  
  12. # 获取mysql中所有数据库
  13. cur.execute('SHOW DATABASES')
  14.  
  15. data_all = cur.fetchall() # 获取执行的返回结果
  16. # print(data_all)
  17.  
  18. for i in data_all:
  19. # 排序列表,排除mysql自带的数据库
  20. exclude_list = ["sys", "information_schema", "mysql", "performance_schema"]
  21. if i[0] not in exclude_list: # 判断不在列表中时
  22. conn.select_db(i[0]) # 切换到指定的库中
  23. cur.execute('SHOW TABLES') # 查看库中所有的表
  24. ret = cur.fetchall() # 获取执行结果
  25.  
  26. for j in ret:
  27. # 获取每一个表的建表语句
  28. cur.execute('show create table `%s`;' % j[0])
  29. ret = cur.fetchall()
  30. # print(ret)
  31. for k in ret:
  32. # 替换反斜杠,使用\\。替换换行符\n,使用下面的
  33. structure = eval(repr(k[1]).replace('\\n ', ''))
  34. # 使用COMMENT= 切割
  35. res = structure.split("COMMENT=")
  36. print(res)

执行输出:

  1. ['CREATE TABLE `school` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci']
  2. ["CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '姓名',PRIMARY KEY (`id`),KEY `ix_users_name` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ", "'用户表'"]

注意: 有些表,是没有写表注释的,所以获取表说明时,要加一个判断

  1. import pymysql
  2.  
  3. conn = pymysql.connect(
  4. host="127.0.0.1", # mysql ip地址
  5. user="root",
  6. passwd="",
  7. port=3306 # mysql 端口号,注意:必须是int类型
  8. )
  9.  
  10. cur = conn.cursor() # 创建游标
  11.  
  12. # 获取mysql中所有数据库
  13. cur.execute('SHOW DATABASES')
  14.  
  15. data_all = cur.fetchall() # 获取执行的返回结果
  16. # print(data_all)
  17.  
  18. for i in data_all:
  19. # 排序列表,排除mysql自带的数据库
  20. exclude_list = ["sys", "information_schema", "mysql", "performance_schema"]
  21. if i[0] not in exclude_list: # 判断不在列表中时
  22. conn.select_db(i[0]) # 切换到指定的库中
  23. cur.execute('SHOW TABLES') # 查看库中所有的表
  24. ret = cur.fetchall() # 获取执行结果
  25.  
  26. for j in ret:
  27. # 获取每一个表的建表语句
  28. cur.execute('show create table `%s`;' % j[0])
  29. ret = cur.fetchall()
  30. # print(ret)
  31. for k in ret:
  32. # 替换反斜杠,使用\\。替换换行符\n,使用下面的
  33. structure = eval(repr(k[1]).replace('\\n ', ''))
  34. # 使用COMMENT= 切割,获取表说明
  35. res = structure.split("COMMENT=")
  36.  
  37. if len(res) > 1: # 判断有表说明的情况下
  38. explain = res[1] # 表说明
  39. print(explain)

执行输出:

  1. '用户表'

输出结果是带有引号的,要去除引号,怎么操作?

使用strip就可以了

  1. import pymysql
  2.  
  3. conn = pymysql.connect(
  4. host="127.0.0.1", # mysql ip地址
  5. user="root",
  6. passwd="",
  7. port=3306 # mysql 端口号,注意:必须是int类型
  8. )
  9.  
  10. cur = conn.cursor() # 创建游标
  11.  
  12. # 获取mysql中所有数据库
  13. cur.execute('SHOW DATABASES')
  14.  
  15. data_all = cur.fetchall() # 获取执行的返回结果
  16. # print(data_all)
  17.  
  18. for i in data_all:
  19. # 排序列表,排除mysql自带的数据库
  20. exclude_list = ["sys", "information_schema", "mysql", "performance_schema"]
  21. if i[0] not in exclude_list: # 判断不在列表中时
  22. conn.select_db(i[0]) # 切换到指定的库中
  23. cur.execute('SHOW TABLES') # 查看库中所有的表
  24. ret = cur.fetchall() # 获取执行结果
  25.  
  26. for j in ret:
  27. # 获取每一个表的建表语句
  28. cur.execute('show create table `%s`;' % j[0])
  29. ret = cur.fetchall()
  30. # print(ret)
  31. for k in ret:
  32. # 替换反斜杠,使用\\。替换换行符\n,使用下面的
  33. structure = eval(repr(k[1]).replace('\\n ', ''))
  34. # 使用COMMENT= 切割
  35. res = structure.split("COMMENT=")
  36.  
  37. if len(res) > 1:
  38. explain = res[1] # 表说明
  39. # print(explain)
  40. explain_new = explain.strip("'") # 去掉引号
  41. print(explain_new)

执行输出:

  1. 用户表

接下来就需要将数据写入到excel中,但是,我们需要知道。写入excel,要不断的调整方位。

由于线上表众多,获取一次数据,需要几分钟时间,时间上耗费不起!

所以为了避免这种问题,需要将获取到的数据,写入json文件中。

构造json数据

既然要构造json数据,那么数据格式,要规划好才行!我构造的数据格式如下:

  1. dic = {
  2. "库名":{
  3. 'name': "库名", 'table_list': [
  4. {'tname':"表名",'structure':"建表语句",'explain':"表说明"}
  5. ]
  6. }
  7. }

从上面可以看出,这是一个三层的数据嵌套

定义一个大字典,写入数据

  1. import pymysql
  2.  
  3. conn = pymysql.connect(
  4. host="127.0.0.1", # mysql ip地址
  5. user="root",
  6. passwd="",
  7. port=3306 # mysql 端口号,注意:必须是int类型
  8. )
  9.  
  10. cur = conn.cursor() # 创建游标
  11.  
  12. # 获取mysql中所有数据库
  13. cur.execute('SHOW DATABASES')
  14.  
  15. data_all = cur.fetchall() # 获取执行的返回结果
  16. # print(data_all)
  17.  
  18. dic = {} # 大字典,第一层
  19. for i in data_all:
  20. if i[0] not in dic: # 判断库名不在dic中时
  21. # 排序列表,排除mysql自带的数据库
  22. exclude_list = ["sys", "information_schema", "mysql", "performance_schema"]
  23. if i[0] not in exclude_list: # 判断不在列表中时
  24. # 写入第二层数据
  25. dic[i[0]] = {'name': i[0], 'table_list': []}
  26. conn.select_db(i[0]) # 切换到指定的库中
  27. cur.execute('SHOW TABLES') # 查看库中所有的表
  28. ret = cur.fetchall() # 获取执行结果
  29.  
  30. for j in ret:
  31. # 获取每一个表的建表语句
  32. cur.execute('show create table `%s`;' % j[0])
  33. ret = cur.fetchall()
  34. # print(ret)
  35. for k in ret:
  36. # 替换反斜杠,使用\\。替换换行符\n,使用下面的
  37. structure = eval(repr(k[1]).replace('\\n ', ''))
  38. # 使用COMMENT= 切割
  39. res = structure.split("COMMENT=")
  40.  
  41. if len(res) > 1:
  42. explain = res[1] # 表说明
  43. # print(explain)
  44. explain_new = explain.strip("'") # 去掉引号
  45. # 写入第三层数据,分别是表名,建表语句,表说明
  46. dic[i[0]]['table_list'].append({'tname': k[0], 'structure': structure,'explain':explain_new})
  47.  
  48. print(dic)

执行输出:

  1. {'db1': {'name': 'db1', 'table_list': [{'tname': 'users', 'structure': "CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '姓名',PRIMARY KEY (`id`),KEY `ix_users_name` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表'", 'explain': '用户表'}]}}

写入json文件

  1. import pymysql
  2. import json
  3.  
  4. conn = pymysql.connect(
  5. host="127.0.0.1", # mysql ip地址
  6. user="root",
  7. passwd="",
  8. port=3306 # mysql 端口号,注意:必须是int类型
  9. )
  10.  
  11. cur = conn.cursor() # 创建游标
  12.  
  13. # 获取mysql中所有数据库
  14. cur.execute('SHOW DATABASES')
  15.  
  16. data_all = cur.fetchall() # 获取执行的返回结果
  17. # print(data_all)
  18.  
  19. dic = {} # 大字典,第一层
  20. for i in data_all:
  21. if i[0] not in dic: # 判断库名不在dic中时
  22. # 排序列表,排除mysql自带的数据库
  23. exclude_list = ["sys", "information_schema", "mysql", "performance_schema"]
  24. if i[0] not in exclude_list: # 判断不在列表中时
  25. # 写入第二层数据
  26. dic[i[0]] = {'name': i[0], 'table_list': []}
  27. conn.select_db(i[0]) # 切换到指定的库中
  28. cur.execute('SHOW TABLES') # 查看库中所有的表
  29. ret = cur.fetchall() # 获取执行结果
  30.  
  31. for j in ret:
  32. # 获取每一个表的建表语句
  33. cur.execute('show create table `%s`;' % j[0])
  34. ret = cur.fetchall()
  35. # print(ret)
  36. for k in ret:
  37. # 替换反斜杠,使用\\。替换换行符\n,使用下面的
  38. structure = eval(repr(k[1]).replace('\\n ', ''))
  39. # 使用COMMENT= 切割
  40. res = structure.split("COMMENT=")
  41.  
  42. if len(res) >= 1:
  43. if len(res) == 1:
  44. explain = ""
  45. else:
  46. explain = res[1] # 表说明
  47. # print(explain)
  48. explain_new = explain.strip("'") # 去掉引号
  49. # 写入第三层数据,分别是表名,建表语句,表说明
  50. dic[i[0]]['table_list'].append({'tname': k[0], 'structure': structure,'explain':explain_new})
  51.  
  52. # print(dic)
  53. with open('tj.json','w',encoding='utf-8') as f:
  54. f.write(json.dumps(dic))

执行程序,查看tj.json文件内容

  1. {"db1": {"name": "db1", "table_list": [{"tname": "users", "structure": "CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '\u59d3\u540d',PRIMARY KEY (`id`),KEY `ix_users_name` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='\u7528\u6237\u8868'", "explain": "\u7528\u6237\u8868"}]}}

四、写入excel中

坐标体系

a1单元格的坐标为0,0。在xlrd模块里面,坐标都是数字,所以不能用a1表示。

坐标如下:

先来写入一段示例数据

新建文件excel.py,代码如下:

  1. import xlwt
  2. f = xlwt.Workbook()
  3. sheet1 = f.add_sheet('学生',cell_overwrite_ok=True)
  4. row0 = ["姓名","年龄","出生日期","爱好"]
  5. colum0 = ["张三","李四","王五"]
  6. #写第一行
  7. for i in range(0,len(row0)):
  8. sheet1.write(0,i,row0[i])
  9.  
  10. #写第一列
  11. for i in range(0,len(colum0)):
  12. sheet1.write(i+1,0,colum0[i])
  13.  
  14. # 写入一行数据
  15. sheet1.write(1,1,"")
  16. sheet1.write(1,2,"")
  17. sheet1.write(1,3,"女")
  18.  
  19. f.save('test.xls')

执行程序,查看excel文件内容

正式写入excel中

写入库名

熟悉语法之后,就可以写入到excel中了

编辑 excel.py,代码如下:

  1. import xlwt
  2. import json
  3. f = xlwt.Workbook()
  4. sheet1 = f.add_sheet('统计', cell_overwrite_ok=True)
  5. row0 = ["库名", "表名", "表说明", "建表语句"]
  6.  
  7. # 写第一行
  8. for i in range(0, len(row0)):
  9. sheet1.write(0, i, row0[i])
  10.  
  11. # 加载json文件
  12. with open("tj.json", 'r') as load_f:
  13. load_dict = json.load(load_f) # 反序列化文件
  14.  
  15. num = 0 # 计数器
  16. for i in load_dict:
  17. # 写入库名
  18. sheet1.write(num + 1, 0, i)
  19.  
  20. f.save('test1.xls')

执行程序,查看excel文件

写入表名

  1. import xlwt
  2. import json
  3. f = xlwt.Workbook()
  4. sheet1 = f.add_sheet('统计', cell_overwrite_ok=True)
  5. row0 = ["库名", "表名", "表说明", "建表语句"]
  6.  
  7. # 写第一行
  8. for i in range(0, len(row0)):
  9. sheet1.write(0, i, row0[i])
  10.  
  11. # 加载json文件
  12. with open("tj.json", 'r') as load_f:
  13. load_dict = json.load(load_f) # 反序列化文件
  14.  
  15. num = 0 # 计数器
  16. for i in load_dict:
  17. # 写入库名
  18. sheet1.write(num + 1, 0, i)
  19. # 遍历所有表
  20. for j in load_dict[i]["table_list"]:
  21. # 写入表名
  22. sheet1.write(num + 1, 1, j['tname'])
  23.  
  24. f.save('test1.xls')

执行程序,查看excel文件

写入表说明和建表语句

  1. import xlwt
  2. import json
  3. f = xlwt.Workbook()
  4. sheet1 = f.add_sheet('统计', cell_overwrite_ok=True)
  5. row0 = ["库名", "表名", "表说明", "建表语句"]
  6.  
  7. # 写第一行
  8. for i in range(0, len(row0)):
  9. sheet1.write(0, i, row0[i])
  10.  
  11. # 加载json文件
  12. with open("tj.json", 'r') as load_f:
  13. load_dict = json.load(load_f) # 反序列化文件
  14.  
  15. num = 0 # 计数器
  16. for i in load_dict:
  17. # 写入库名
  18. sheet1.write(num + 1, 0, i)
  19. # 遍历所有表
  20. for j in load_dict[i]["table_list"]:
  21. # 写入表名
  22. sheet1.write(num + 1, 1, j['tname'])
  23. # 写入表说明
  24. sheet1.write(num + 1, 2, j['explain'])
  25. # 写入建表语句
  26. sheet1.write(num + 1, 3, j['structure'])
  27. num += 1 # 自增1
  28.  
  29. f.save('test1.xls')

注意:默认的num必须要自增,否则多个数据库写入会有问题

执行程序,查看excel文件

总结:

案例只是写入一个数据库,那么多个数据库,也是同样的代码。

有序字典

假设说,excel的内容是这样的

我需要对库名做一个排序,将abc和adb放在前2行,第三行是db1。该如何操作呢?

对于python 3.6之前,默认的字典都是无序的。如果需要将普通字典转换为有序字典,需要使用OrderedDict

举例:

  1. from collections import OrderedDict
  2. dic = {"k":1,"a":2,"d":4}
  3. order_dic = OrderedDict() # 实例化一个有序字典
  4. for i in sorted(dic): # 必须先对普通字典key做排序
  5. order_dic[i] = dic[i] # 写入有序字典中
  6.  
  7. print(order_dic)

执行输出:

  1. OrderedDict([('a', 2), ('d', 4), ('k', 1)])

注意:将普通字典转换为有序字典时,必须要先对普通字典,做一次排序。那么之后写入到有序字典之后,顺序就是有序了!

不论执行多少次print,结果都是一样的!

改造excel写入

编辑 excel.py,代码如下:

  1. import xlwt
  2. import json
  3. from collections import OrderedDict
  4.  
  5. f = xlwt.Workbook()
  6. sheet1 = f.add_sheet('统计', cell_overwrite_ok=True)
  7. row0 = ["库名", "表名", "表说明", "建表语句"]
  8.  
  9. # 写第一行
  10. for i in range(0, len(row0)):
  11. sheet1.write(0, i, row0[i])
  12.  
  13. # 加载json文件
  14. with open("tj.json", 'r') as load_f:
  15. load_dict = json.load(load_f) # 反序列化文件
  16. order_dic = OrderedDict() # 有序字典
  17. for key in sorted(load_dict): # 先对普通字典key做排序
  18. order_dic[key] = load_dict[key] # 再写入key
  19.  
  20. num = 0 # 计数器
  21. for i in order_dic:
  22. # 写入库名
  23. sheet1.write(num + 1, 0, i)
  24. # 遍历所有表
  25. for j in order_dic[i]["table_list"]:
  26. # 写入表名
  27. sheet1.write(num + 1, 1, j['tname'])
  28. # 写入表说明
  29. sheet1.write(num + 1, 2, j['explain'])
  30. # 写入建表语句
  31. sheet1.write(num + 1, 3, j['structure'])
  32.  
  33. num += 1 # 自增1
  34.  
  35. f.save('test1.xls')

执行程序,效果同上(因为数据太少了)

python 统计MySQL表信息的更多相关文章

  1. Python 基于Python从mysql表读取千万数据实践

    基于Python 从mysql表读取千万数据实践   by:授客 QQ:1033553122 场景:   有以下两个表,两者都有一个表字段,名为waybill_no,我们需要从tl_waybill_b ...

  2. Python 3 mysql 表操作

    Python 3 mysql 表操作 表相当于文件,表中的一条记录就相当于文件的一行内容,不同的是,表中的一条记录有对应的标题,称为表的字段 id,name,qq,age称为字段,其余的,一行内容称为 ...

  3. Python将MySQL表数据写入excel

    背景:将mysql表查询结果写入excel. 1.使用sqlyog工具将查询结果导出到Excel.xml中,用excel打开发现:因为text字段中有回车换行操作,显示结果行是乱的. 2.用mysql ...

  4. python 统计MySQL大于100万的表

    一.需求分析 线上的MySQL服务器,最近有很多慢查询.需要统计出行数大于100万的表,进行统一优化. 需要筛选出符合条件的表,统计到excel中,格式如下: 库名 表名 行数 db1 users 1 ...

  5. python统计nginx脚本信息

    #!/usr/bin/env python # -*- coding: utf-8 -*- import urllib2 import json import subprocess import th ...

  6. 解决Python查询Mysql数据库信息乱码问题

    今天尝试着用 Python 写了个脚本试着连接 mysql 数据库,并查询里边的数据,不过最终查询结果中文字符变成了ascii格式. 代码如下: #!/usr/bin/python #encoding ...

  7. python开发mysql:表关系&单表简单查询

    一 一对多,多对一 1.1 建立多对一 ,一对多的关系需要注意 先建立被关联的表,被关联的字段必须保证时唯一的 在创建关联的表,关联的字段一定是可以重复的 1.2 示例: 出版社 多对一,多个老师可能 ...

  8. python 多线程删除MySQL表

    一.需求分析 在<python 统计MySQL表信息>这篇博客中,链接如下: https://www.cnblogs.com/xiao987334176/p/9901692.html 已经 ...

  9. (转)【mysql元数据库】使用information_schema.tables查询数据库和数据表信息 ---数据记录大小统计

    转:https://www.cnblogs.com/ssslinppp/p/6178636.html https://segmentfault.com/q/1010000007268994?_ea=1 ...

随机推荐

  1. PHP判断变量类型和类型转换的三种方式

    前言: PHP 在变量定义中不需要(不支持)明确的类型定义.变量类型是根据使用该变量的上下文所决定的.所以,在面对页码跳转.数值计算等严格的格式需求时,就要对变量进行类型转换. 举例如下: $foo ...

  2. 学习Oracle的一些收获

    前言: 在看尚硅谷的Oracle视频时,总结的一些自己之前不熟的,或者完全不了解的知识点,只适用于本人,本人有一定的SQL基础,所以一些我比较熟悉的知识点不会列出来. Oracle中SQL使用技巧: ...

  3. 关于JSON的解析方式

    借鉴:站在巨人的肩膀上 一.json-lib json-lib最开始的也是应用最广泛的json解析工具,json-lib 不好的地方确实是依赖于很多第三方包,在Json.org网站上,Java可以使用 ...

  4. vue 打印页面部分区域

    1. vue项目打印页面部分区域 2. 原生js实现页面局部打印功能 3. vue项目中将table组件导出Excel表格以及打印页面内容

  5. centos7.2云主机安装桌面

    yum groups install "X Window System" yum groupinstall "GNOME Desktop" systemctl  ...

  6. jvm内存模型(运行时数据区)

    运行时数据区(runtime data area) jvm定义了几个运行时数据区,这些运行时数据区存储的数据,供开发者的应用或者jvm本身使用.按线程共享与否可以分为线程间共享和线程间独立. 线程间独 ...

  7. Linux基础命令【记录】

    后台运行详情:https://www.cnblogs.com/little-ant/p/3952424.html 查看端口.查找等命令 根据关键字查找文件信息: cat <文件名> | g ...

  8. Nginx location 配置用法及正则例子

    Nginx location 配置语法     1. location [ = | ~ | ~* | ^~ ] uri { ... }     2. location @name { ... }   ...

  9. 6 Easy Steps to Learn Naive Bayes Algorithm (with code in Python)

    6 Easy Steps to Learn Naive Bayes Algorithm (with code in Python) Introduction Here’s a situation yo ...

  10. 苏宁OLAP架构设计

    一. 功能综述 OLAP引擎为存储和计算二合一的引擎,自身内部涵盖了对数据的管理以及提供查询能力.底层数据完全规划在引擎内部,外部系统不允许直接操作底层数据,而是需要通过暴露出来的接口来读写引擎内部数 ...