轉換csv檔案為插入的sql腳本【本地轉換實作方案】
背景:
公司資料從其中一台伺服器上的資料庫中導出成csv格式,有時為了友善進行本地資料的調試,需要将這些資料進行插入到一個測試庫中,一條條去轉換為insert語句,耗時也耗人力成本,那能不能針對導出的檔案進行轉換,生成高效的insert的sql腳本呢?
解決方案:
1.檢視導出的csv檔案内容格式
前面是一個資料庫名字,後面跟着一個查詢語句,接下來是表的資料
我們發現,如果沒有資料的,會直接線上無資料,那樣,這個表就不需要生成insert腳本了
然後有多條資料的,如果一條條的插入,那樣會造成頻繁的資料連接配接通路,插入效率低下,需要進行優化,一個庫表就隻生成一條插入語句就好了,當然這個是針對MYSQL的插入方式的優化,其他資料庫需要再進行定制化。
2.進行csv檔案内容的解析
def TransFile(self):
"""
檔案解析
:return:
"""
if not os.path.exists(self.CSVFile):
return None
sqlrow = ''
tbcols = ''
colstart = 0
with open(self.CSVFile, 'r', encoding='gbk') as csvf:
rowreader = csv.reader(csvf)
for row in rowreader:
if len(row) > 3:
if row[0] == '' and row[1] == '' and row[2] == '':
# 空行直接跳過
continue
for item in row:
# if item == '':
# break
if len(str(item).split(':select')) == 2:
if len(sqlrow) > 1:
sqlrow = sqlrow[:-2] + ';\n'
self.saveTbSql(sqlrow)
tbstart = True
colstart = 1
tbcols = ''
tbname = str(item).split('from')[1].split('where')[0].strip(' ')
print(tbname)
sqlrow = 'insert into `{}`'.format(tbname)
if tbname.find('cq_user_title') > 0:
pass
break
if str(item) == '無資料':
#如果沒有資料的則不生成insert sql腳本
sqlrow = ''
tbstart = False
break
if tbcols == '':
tbcols = "'{}'".format(item)
else:
tbcols = "{},'{}'".format(tbcols, item)
if tbstart == True:
#加入insert into的表頭
if colstart >= 2:
tbstart = False
sqlrow = '{}({})values\n'.format(sqlrow, tbcols.replace("'", "`"))
tbcols = ''
colstart +=1
else:
sqlrow = '{}({}),\n'.format(sqlrow, tbcols)
tbcols = ''
#儲存最後的一個表的資料
if len(sqlrow) > 1:
sqlrow = sqlrow[:-2] + ';\n'
self.saveTbSql(sqlrow)
csvf.close()
self.TranssaveTbSql()
return self.WebbasePath, self.WebDir, self.SaveFile
3.進行insert的sql檔案的儲存
def saveTbSql(self,rowinfo):
"""
儲存腳本
:param rowinfo:
:return:
"""
if rowinfo == '();\n':
return
transrow = str(rowinfo).replace(',;', ';').replace(',()', '').replace('(),\n','')
if transrow == '':
return
with open('{}{}'.format(self.WebbasePath, self.SaveFile), 'a+', encoding='gbk') as sqlf:
sqlf.write(transrow)
sqlf.close()
4.進行多條insert腳本的合并,生成高效的插入腳本
def TranssaveTbSql(self):
"""
儲存腳本
:param rowinfo:
:return:
"""
with open('{}{}'.format(self.WebbasePath, self.SaveFile), 'r', encoding='gbk') as sqlf:
rowinfo = sqlf.readlines()
with open('{}{}tmp'.format(self.WebbasePath, self.SaveFile), 'a+', encoding='gbk') as sqlftmp:
index = -1
rowcount = len(rowinfo)
for row in rowinfo:
index +=1
# if index == 0:
# #第一行的空的去掉
# continue
transrow = str(row).replace(';*****', ';').replace(',()', '').replace(",'','',''", '').replace(",``", '')
transrow = transrow.replace(",'')", '==*==').replace('==*==', ')').\
replace(",'')", '==*==').replace('==*==', ')')
if rowcount - 1 == index:
transrow = transrow.replace('),', ');')
sqlftmp.write(transrow)
sqlftmp.close()
sqlf.close()
os.remove('{}{}'.format(self.WebbasePath, self.SaveFile))
os.renames('{}{}tmp'.format(self.WebbasePath, self.SaveFile), '{}{}'.format(self.WebbasePath, self.SaveFile))
5.制作本地用戶端的錄入界面
打開生成的sql檔案,就會看到類似這樣的結果了:
在本地會有這樣的sql檔案生成
這個是每次轉換都會生成一個sql檔案,可以直接拿着這個生成好的sql腳本進行刷庫了。
結語:
好的這次的分享就到這,感謝閱讀!