掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
我是一名掙扎在編程鏈底端的pythoner,工作中既要和數(shù)據(jù)打交道,也要保持和erp系統(tǒng),web網(wǎng)站友好的"溝通"···,我會時不時的分享下工作中遇到那點事,包括個人覺得值得記錄的編程小技巧,還有就是遇到的問題以及解決方案,還有源碼的閱讀等等,可能也有編程中的生活感悟,不說了,我要去重構(gòu)我的程序了

網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、重慶小程序開發(fā)公司、集團企業(yè)網(wǎng)站建設(shè)等服務(wù)項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了豐滿免費建站歡迎大家使用!
本文基于python, 使用pandas, pymysql等三方庫實現(xiàn)了向數(shù)據(jù)庫中高效批量插入數(shù)據(jù),一方面提供被網(wǎng)上很多瞎轉(zhuǎn)載的答案給坑蒙了的人(因為我也是),一方面自己也做個筆記,以后方便查閱
最近在處理一個需求,有關(guān)批量往數(shù)據(jù)庫插入數(shù)據(jù)的,描述如下
實際上,最后一步,要寫入數(shù)據(jù)庫的文件數(shù)據(jù)是存儲在內(nèi)存中的。因為讀取文件后進行的計算都是在內(nèi)存中進行的,那么計算的結(jié)果也沒必要再寫到本地,再去讀取,再寫入數(shù)據(jù)庫,這是會影響程序的效率的。邏輯如下
讀取文件
給文件路徑,然后去讀文件就行了,強調(diào)一下需要注意的點
- import pandas as pd
- import numpy as np
- # 當前腳本的位置
- current_folder_path = os.path.dirname(__file__)
- # 你的文件的位置
- your_file_path1 = os.path.join(current_folder_path, "文件的名字1")
- your_file_path2 = os.path.join(current_folder_path, "文件的名字2")
- # 我這里是以讀取csv文件為例, delimiter為我們內(nèi)部約定的列之間的分割符
- df1 = pd.read_csv(your_file_path1, dtype={"column1": str, "column2": str}, delimiter="/t")
- df2 = pd.read_csv(your_file_path2, dtype={"column1": str, "column2": str}, delimiter="/t")
文件的拼接及計算
文件的拼接主要就是merge和concat兩個語法的使用,強調(diào)一下小知識點
- # 這里以左連接舉例, 假設(shè)只有兩個文件拼接
- ret_df = pd.merge(df1, df2, left_on=["column_name"], right_on=["column_name"], how="left")
初始化連接
導入三方庫pymysql,初始化連接
- # pymysql的接口獲取鏈接
- def mysql_conn(host, user, password, db, port=3306, charset="utf8"):
- # 傳參版本
- conn = pymysql.connect(host=host, user=user, password=password, database=db, port=port, charset=charset)
- return conn
對應(yīng)接口轉(zhuǎn)換數(shù)據(jù)
具體實現(xiàn)如下
- # 先創(chuàng)建cursor負責操作conn接口
- conn = mysql_conn("your db host", "your username", "your password", "db name")
- cursor = conn.cursor()
- # 開啟事務(wù)
- conn.begin()
- ############# 構(gòu)造批量數(shù)據(jù)的過程 #############
- # 先構(gòu)造需要的或是和數(shù)據(jù)庫相匹配的列
- columns = list(df.columns)
- # 可以刪除不要的列或者數(shù)據(jù)庫沒有的列名
- columns.remove("列名")
- # 重新構(gòu)造df,用上面的columns,到這里你要保證你所有列都要準備往數(shù)據(jù)庫寫入了
- new_df = df[columns].copy()
- # 構(gòu)造符合sql語句的列,因為sql語句是帶有逗號分隔的,(這個對應(yīng)上面的sql語句的(column1, column2, column3))
- columns = ','.join(list(new_df.columns))
- # 構(gòu)造每個列對應(yīng)的數(shù)據(jù),對應(yīng)于上面的((value1, value2, value3))
- data_list = [tuple(i) for i in gdsord_df.values] # 每個元組都是一條數(shù)據(jù),根據(jù)df行數(shù)生成多少元組數(shù)據(jù)
- # 計算一行有多少value值需要用字符串占位
- s_count = len(data_list[0]) * "%s,"
- # 構(gòu)造sql語句
- insert_sql = "insert into " + "數(shù)據(jù)庫表名" + " (" + columns + ") values (" + s_count[:-1] + ")"
將數(shù)據(jù)寫入數(shù)據(jù)庫
這個簡單,直接上代碼
- cursor.executemany(insert_sql, data_list)
- conn.commit()
- cursor.close()
- conn.close()
檢查數(shù)據(jù)庫是否插入成功
如果沒問題的話,就可以同時進行多個文件讀寫,計算,最后啟用多線程同時向數(shù)據(jù)庫中寫入數(shù)據(jù)了,非常高效!
完整代碼
- import pandas as pd
- import numpy as np
- # pymysql接口
- def mysql_conn(host, user, password, db, port=3306, charset="utf8"):
- conn = pymysql.connect(host=host, user=user, password=password, database=db, port=port, charset=charset)
- return conn
- # 當前腳本的位置
- current_folder_path = os.path.dirname(__file__)
- # 你的文件的位置
- your_file_path1 = os.path.join(current_folder_path, "文件的名字1")
- your_file_path2 = os.path.join(current_folder_path, "文件的名字2")
- # 我這里是以讀取csv文件為例, delimiter為我們內(nèi)部約定的列之間的分割符
- df1 = pd.read_csv(your_file_path1, dtype={"column1": str, "column2": str}, delimiter="/t")
- df2 = pd.read_csv(your_file_path2, dtype={"column1": str, "column2": str}, delimiter="/t")
- # 合并
- ret_df = pd.merge(df1, df2, left_on=["column_name"], right_on=["column_name"], how="left")
- # 先創(chuàng)建cursor負責操作conn接口
- conn = mysql_conn("your db host", "your username", "your password", "db name")
- cursor = conn.cursor()
- # 開啟事務(wù)
- conn.begin()
- # 先構(gòu)造需要的或是和數(shù)據(jù)庫相匹配的列
- columns = list(df.columns)
- # 可以刪除不要的列或者數(shù)據(jù)庫沒有的列名
- columns.remove("列名")
- # 重新構(gòu)造df,用上面的columns,到這里你要保證你所有列都要準備往數(shù)據(jù)庫寫入了
- new_df = df[columns].copy()
- # 構(gòu)造符合sql語句的列,因為sql語句是帶有逗號分隔的,(這個對應(yīng)上面的sql語句的(column1, column2, column3))
- columns = ','.join(list(new_df.columns))
- # 構(gòu)造每個列對應(yīng)的數(shù)據(jù),對應(yīng)于上面的((value1, value2, value3))
- data_list = [tuple(i) for i in gdsord_df.values] # 每個元組都是一條數(shù)據(jù),根據(jù)df行數(shù)生成多少元組數(shù)據(jù)
- # 計算一行有多少value值需要用字符串占位
- s_count = len(data_list[0]) * "%s,"
- # 構(gòu)造sql語句
- insert_sql = "insert into " + "數(shù)據(jù)庫表名" + " (" + columns + ") values (" + s_count[:-1] + ")"
- try:
- cursor.executemany(insert_sql, data_list)
- conn.commit()
- cursor.close()
- conn.close()
- except Exception as e:
- # 萬一失敗了,要進行回滾操作
- conn.rollback()
- cursor.close()
- conn.close()

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流