Python批量導入文本數據到數據庫的方法

最近在工作中碰到一個問題,需要快速的將一些歷史數據導入到數據庫中(CSV格式),經過考慮決定使用python來實現。

主要需要解決以下兩個問題:

1、CSV格式的解釋

2、數據的批量寫入(性能考慮)


一、CSV格式的解釋

CSV格式其實就是文本文件,使用open函數打開文件,然後循環訪問就可以。

先將文件內容讀取到內存中。

def read(self):
"""讀取文件的內容,將文件內容作爲列表返回。"""
lines = []
with open(self.file_name, 'rt', -1, encoding="GB2312") as file:
lines = file.readlines()
count = len(lines)
if count > 0:
del lines[0] #去掉第一行表頭內容。

return lines

二、批量更新數據庫內容

數據批量寫入數據庫有三種形式

1、方法1:將每一行要寫的數據轉爲insert的SQL語句,然後將這些語句拼接成一個長長的字符串,程序一次性的把長長的sQL串傳送到服務器上。

def execute(self, sql):
"""批量處理SQL語句。"""
cursor = self.conn.cursor()
#cursor.execute("begin transaction") #這個語句不能要,會導致數據寫不到數據庫中。
cursor.execute(sql)
self.conn.commit() #提交數據到服務器上。

2、方法2:將每一行要寫的數據轉爲insert的SQL語句,將這些SQL語句一句一句的送給服務器運行,但是不提交事務,到最後才一次性提交

def execute_batch(self, sqls):
"""批量執行SQL語句
sqls => sql語句列表,每一個sql語句都是以分好結尾。
"""
cursor = self.conn.cursor()
for s in sqls:
cursor.execute(s)
self.conn.commit()

3、方法3:使用python庫的executemany方法

def execute_many(self, sqlvalue):
"""參數化執行多個語句"""
cursor = self.conn.cursor()
cursor.executemany(sqlvalue[0], sqlvalue[1])
self.conn.commit()

三、例子

1、文件內容讀取

class TickFile():
"""tick數據文件"""
def __init__(self, fileName):
self.file_name = fileName

def read(self):
"""讀取文件的內容,將文件內容作爲列表返回。"""
lines = []
with open(self.file_name, 'rt', -1, encoding="GB2312") as file:
lines = file.readlines()
count = len(lines)
if count > 0:
del lines[0] #去掉第一行表頭內容。

return lines

2、數據庫訪問包裝類:

class SqlServerProxy():
"""SQL server數據庫訪問代理類。"""
def __init__(self, server, user, password, database):
self.server = server
self.user = user
self.password = password
self.database = database
self.conn = self.__create_connection()

def close(self):
self.conn.close()

def __create_connection(self):
conn = pymssql.connect(server=self.server, user=self.user, password=self.password, database=self.database)
return conn

def execute(self, sql):
"""批量處理SQL語句。"""
cursor = self.conn.cursor()
#cursor.execute("begin transaction") #這個語句不能要,會導致數據寫不到數據庫中。
cursor.execute(sql)
self.conn.commit() #提交數據到服務器上。

def execute_many(self, sqlvalue):
"""參數化執行多個語句"""
cursor = self.conn.cursor()
cursor.executemany(sqlvalue[0], sqlvalue[1])
self.conn.commit()

def execute_batch(self, sqls):
"""批量執行SQL語句
sqls => sql語句列表,每一個sql語句都是以分好結尾。
"""
cursor = self.conn.cursor()
for s in sqls:
cursor.execute(s)
self.conn.commit()

3、解釋數據寫入類:

class SqlWriter():
"""SQL數據寫入類"""
def __init__(self, sqlproxy):
if not isinstance(sqlproxy, SqlServerProxy):
raise ReferenceError("參數sqlproxy不是SqlServerProxy類型。")
self.sql_proxy = sqlproxy

def write_many(self, product, symbol, lines):
sqlvalue = self.__lines_to_sqlmany(product, symbol, lines)
self.sql_proxy.execute_many(sqlvalue)

def write(self, product, symbol, lines):
"""將數據寫入到數據庫中。"""
sqls = []
for line in lines:
sql = self.__line_to_sql(product, symbol, line)
sqls.append(sql)
print(sql)
self.sql_proxy.execute_batch(sqls) #將數據保存到數據庫中去。

def __lines_to_sqlmany(self, product, symbol, lines):
sql = "INSERT INTO Tick_" + product + "(InfoSeq, Symbol, TradeTime, LastPrice, Volumne, AskPrice1, AskVolume1,BidPrice1,BidVolume1,OpenPosition) VALUES (\
%d ,%s ,%s ,%d ,%d ,%d ,%d ,%d ,%d ,0);"
values = []
for line in lines:
arr = line.split(",")
timestring = "%s %s.%s" % (arr[0], arr[1], arr[2])
sqldata = (0, symbol, timestring, arr[3], arr[8], arr[4], arr[5], arr[5], arr[7])
values.append(sqldata)

return sql, values


def __line_to_sql(self, product, symbol, line):
"""將line的數據轉換爲SQL語句。"""
arr = line.split(",")
timestring = "%s %s.%s"%(arr[0], arr[1], arr[2])
print("timestring = %s"%(timestring))
sql = "INSERT INTO Tick_%s(InfoSeq, Symbol, TradeTime, LastPrice, Volumne, AskPrice1, AskVolume1,BidPrice1,BidVolume1,OpenPosition) VALUES (\
%d\
,'%s'\
,'%s'\
,%s\
,%s\
,%s\
,%s\
,%s\
,%s\
,0\
);"%(product, 0, symbol, timestring, arr[3], arr[8], arr[4], arr[5], arr[5], arr[7])
return sql

備註:需要引用的python包

import pymssql
import os
import pymssql


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章