关于使用python来实现mysql自动生成数据表

注:环境 windows 7 旗舰版
python 3.6.4 xlrd模块 pymysql模块
mysql 8.0.12
前几天拿到一个项目需要在数据库创建‘一堆’的表!于是就有了一个偷懒的想法!
经过努力终于完成了‘乞丐版’代码如下:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import pymysql
import xlrd

 #先写一个函数,用来读取xlsx,并生成可执行的mysql命令
def read_xlrd(s):
    Sfile = xlrd.open_workbook(filename=s)  #读取xlsx文件 filename为关键字s是文件路径+名字
    Sfile.sheet_names()  # 获取Excel文件 sheet名
    sheet = Sfile.sheet_by_index(0)   #获取第n页 sheet对象    index(n)  n 从0开始
    #如果这里有多页,可以进行遍历获取
    print(sheet.name, sheet.nrows, sheet.ncols)
    # 获取当前sheet的名字  sheet行数     sheet列数
    # rows = sheet.row_values(10)
    # 获取当前sheet中某一整行的数据rows为一个列表
    for i in range(0, sheet.nrows):  # 循环遍历每一行,0到该表格的最大行,for顾头不顾尾
        h = sheet.row_values(i)  #获取当前sheet 第 i 行的数据  h为一个列表
        field_name, field_type, isNull, restrain = '', '', '', ''   #初始化一些变量
        b = 0
        #通过以下判断来拼接对应的字符串
        if i == 0:
            table_name = h[0]  # 表名
            l = 'create table {} ('.format(table_name)     
        elif h[0] == '': #如果该行的数据的第0位也就是字段名为空,则表示该行为合并过
                             #的单元格,无数据
            b = 1        #所以跳过改行以后的判断,并将变量b值改为1 后面会用到
            pass
        else:
            field_name = h[0] + ' '  # 字段名称  每行的第0位为字段名,mysql语句均以空格分隔,所以在后边加一个空格
            field_type = h[1] + ' '  # 字段类型   每行第1位为字段类型
            if h[2] == 'N':     #每行第2位,声明该字段是否可以为空,表中以‘N’表示不可为空
                isNull = 'not null '  # 是否为空   给变量赋值
            elif h[2] == '':  #每行的这一位可能为空
                isNull = ''    #如果为空给变量赋值为空
            if h[3] == '主键':  #通过第3位判断该字段是否为主键
                restrain = 'primary key'  # 约束条件,给变量赋值
                isNull = ''   #主键一定不可为空,非空声明可以取消
            elif h[3] == '全表唯一性': #通过第3位判断该字段是否为唯一
                restrain = 'unique key'  #给变量赋值
            elif h[3] == '':   #判断无约束条件时
                restrain = ''  #赋值为空
        if i == sheet.nrows - 1:  #判断是否已经读到表格的最后一行
            l = l + field_name + field_type + isNull + restrain + ') character set utf8;' 
            #拼接mysql语句尾部与分号
        elif i == 0 or b == 1:  #第一行和空行不需要进行拼接,直接跳过
            pass
        else:  #正常行均进行拼接每个字段的结尾加逗号
            l = l + field_name + field_type + isNull + restrain + ','
        # 生成sql语句
       #所有行都读完后mysql语句拼接完成,返回给调用语句
    return l
#settings部分可以提出来拿到配置文件中
settings = {
    'host': '127.0.0.1',  #为了方便测试,这里使用本地的
    'port': 3306,      #连接端口   mysql 默认3306
    'database': 'ajia',    #要连接的数据库名
    'password': '123456',    #数据库密码
    'charset': 'utf8',     #字符集
    'user': 'root',      #连接用户
}
conn = pymysql.connect(**settings)  #连接数据库
cur = conn.cursor()   #创建游标
cur.execute(r'use ajia;')  
#上边的r'use ajia'可以替换为 'use {};'.format(settings['database'])


#下面假设有13张表,我使用for循环来进行遍历,具体操作时可以将这里提取出来拿到配置文件中,这里要考虑文件名之间的关联性来生成路径
********************
for i in range(1, 14):
    bt = R'/0{}.xlsx'.format(i)    #文件名
    s = R"D:/xlsx13" + str(bt)  #文件路径+
    l = read_xlrd(s)    #调用函数并传参
    print(l)           #打印返回值
    cur.execute(l)   #执行生成的mysql命令
conn.commit()
cur.close()  #关闭游标
conn.close() #断开连接

我们以下面这张表做示例:
关于使用python来实现mysql自动生成数据表_第1张图片
为了方便操作,我对这张表进行了些许处理 观察这张表可以发现,第一行是完全不用出现在mysql命令里的!在mysql创建数据表时需要一个表名称,所以我便将第一行的第一列换成了我们想要创建的表的名称,这样方便我们后续的操作!

整体思路:

1.自动创建的实质是生成mysql语句 观察表可以得到以下:
create table 表名(
字段1 字段类型 [是否允许为空 约束条件],
字段1 字段类型 [是否允许为空 约束条件]
)character set utf8;
可以看到上面这段伪代码中,汉字部分都是需要从xslx文件中获取到并替换的,其余的关键字及字符集都是固定不变的,当然如果需要字符集也是可以手动设置的!
2.有了第一部分的分析,我们就需要使用python的xlrd模块来获取我们想要的数据。
3.成功获取数据后,然后就是将拿到的数据进行判断,根据值的不同对应不同的‘字符串’,然后使用这些字符串替换掉伪代码中的汉字,完成mysql代码的生成!
4.通过pymysql与mysql建立连接,然后将上边拼接完成的字符串传给mysql进行执行,完成表的生成!

遇到的问题

1.最开始是拼接路径的问题,最早文件在桌面win下路径如:C:\Users\Administrator\Desktop\笔记 '\'在python中是转义字符,需要‘\\’,但双斜杠后xlrd.open_workbook(filename=s)就无法读取,尝试加R让解释器不转义,结果也不行,后来查询可大量文件发现可能与windows的桌面汉字路径有关于是将文件整个移动至D盘,加R使用反斜杠成功解决
2.第二次是字符集的问题报错如下:SyntaxError: (unicode error) ‘utf-8’ codec can’t decode byte 0xb4 in position 2:invalid sta 最初使用sublime进行程序格式的转化,结果很不理想,一直是gb2312,无奈之下使用notepad++将gb2312成功转成utf8。程序成功运行。不是很清楚sublime为什么无法完成转码!不过notepad++可以成功!
3.第三个问题也是坑我最深的问题,是关于mysql的最开始我的mysql是5.7版本的,可以看到上边的实例表中有连续几个字段的类型都是timestamp,然后就报了如下错误:pymysql.err.InternalError: (1067, “Invalid default value for ‘updated’” 意思是默认值错误,查资料的结果说是mysql的严格模式,连续的timestamp会插入‘0000-00-00’,而mysql严格模式下认为该数据为非法数据!网上给出了解决办法,修改配置表,于是我就去修改了结果,我的mysql炸了,由于没有备份配置表,导致mysql服务一直无法重启。最后不得已重装了mysql,这次直接安装了8.0.12版本的!也没在报那个错误!至此,‘乞丐版’的自动生成表的程序完成!

多说几句

虽然这只是‘乞丐版’但是核心已经完成,再精进无非是多些判断,多拼接sql语句,既然可以完成表的生成那么表记录的插入呢?当然异曲同工!思想是一致的!这里我就不写了如果你有兴趣可以自己去尝试,还有读取的也不止是xslx文件,还有.docx 等等!有兴趣的话就动手吧骚年!

感谢阅读,希望本文能给你带来些许帮助!

你可能感兴趣的:(小代码,mysql,python)