1. 程式人生 > >關於使用python來實現mysql自動生成資料表

關於使用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() #斷開連線

我們以下面這張表做示例: 為了方便操作,我對這張表進行了些許處理 觀察這張表可以發現,第一行是完全不用出現在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 等等!有興趣的話就動手吧騷年!

感謝閱讀,希望本文能給你帶來些許幫助!