最近在工作中碰到一个问题,需要快速的将一些历史数据导入到数据库中(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