这有点模糊,因为该程序相当深入,但坚持我,因为我会尽力解释它。我编写了一个程序,它接受.csv
文件并将其转换为MySQL数据库的INSERT INTO
语句。例如:
ID Number Letter Decimal Random
0 1 a 1.8 A9B34
1 4 b 2.4 C8J91
2 7 c 3.7 L9O77
将导致插入语句,如:
INSERT INTO table_name ('ID' int, 'Number' int, 'Letter' varchar(). 'Decimal', float(), 'Random' varchar()) VALUES ('0', '1', 'a', '1.8', 'A9B34');
但是并非所有.csv
文件都具有相同的列标题,但它们需要插入到同一个表中。对于没有特定列标题的文件,我想插入NULL
值来显示此信息。例如:
让我们说第一个.csv
文件 A 包含以下信息:
ID Number Decimal Random
0 1 1.8 A9B34
1 4 2.4 C8J91
第二个.csv
文件 B 有不同的列标题:
ID Number Letter Decimal
0 3 x 5.6
1 8 y 4.8
转换为INSERT
语句并放入数据库后,理想情况下如下:
ID TableID Number Decimal Letter Random
0 A 1 1.8 NULL A9B34
1 A 4 2.4 NULL C8J91
2 B 3 5.6 x NULL
3 B 8 4.8 y NULL
现在我可能会开始失去你。
为了完成我需要的工作,我首先获取每个文件并创建所有 {@ 1}}文件的列标题的主列表:
.csv
哪个会从多个def createMaster(path):
global master
master = []
for file in os.listdir(path):
if file.endswith('.csv'):
with open(path + file) as inFile:
csvFile = csv.reader(inFile)
col = next(csvFile) # gets the first line of the file, aka the column headers
master.extend(col) # adds the column headers from each file to the master list
masterTemp = OrderedDict.fromkeys(master) # gets rid of duplicates while maintaining order
masterFinal = list(masterTemp.keys()) # turns from OrderedDict to list
return masterFinal
文件中获取所有列标题,并按顺序将它们组合成主列表,而不会重复:
.csv
这为我提供了['ID', 'Number', 'Decimal', 'Letter', 'Random']
声明的第一部分。现在我需要将INSERT
部分添加到语句中,因此我一次一个地列出每个VALUES
文件的每一行中的所有值。对于每一行,创建一个临时列表,然后将该文件的列标题列表与所有文件的列标题的主列表进行比较。然后它遍历主列表中的每个事物并尝试获取列列表中相同项的索引。如果它在列列表中找到该项,则会将该项从同一索引的行列表中插入临时列表中。如果找不到该项,则会将.csv
插入临时列表中。完成临时列表后,它会将列表转换为正确的MySQL语法字符串,并将其附加到'NULL'
文件以进行插入。这是代码中的相同想法:
.sql
现在是时候了解问题。
此程序的问题是def createInsert(inPath, outPath):
for file in os.listdir(inpath):
if file.endswith('.csv'):
with open(inPath + file) as inFile:
with open(outPath + 'table_name' + '.sql', 'a') as outFile:
csvFile = csv.reader(inFile)
col = next(csvFile) # gets the first row of column headers
for row in csvFile:
tempMaster = [] # creates a tempMaster list
insert = 'INSERT INTO ' + 'table_name' + ' (' + ','.join(master)+ ') VALUES ' # SQL syntax crap
for x in master:
try:
i = col.index(x) # looks for the value in the column list
r = row[i] # gets the row value at the same index as the found column
tempMaster.append(r) # appends the row value to a temporary list
except ValueError:
tempMaster.append('NULL') # if the value is not found in the column list it just appends the string to the row master list
values = map((lambda x: "'" + x.strip() + "'"), tempMaster) # converts tempMaster from a list to a string
printOut = insert + ' (' + ','.join(values) + '):')
outFile.write(printOut + '\n') # writes the insert statement to the file
从tempMaster列表中获取所有行值,并通过以下行与createInsert()
标记连接:
'
这一切都很好,花花公子除了之外,MySQL希望插入values = map((lambda x: "'" + x.strip() + "'"), tempMaster)
个值而不是NULL
而不是NULL
。
如何处理汇总的行列表并搜索'NULL'
字符串并将其更改为'NULL'
?
我有两个不同的想法:
我可以沿着这些行执行某些操作从NULL
标记中提取NULL
字符串并将其替换为列表。
'
或者我可以将def findBetween(s, first, last):
try:
start = s.index(first) + len(first)
end = s.index(last, start)
return s[start:end]
except ValueError:
print('ERROR: findBetween function failure.')
def removeNull(aList):
tempList = []
for x in aList:
if x == 'NULL':
norm = findBetween(x, "'", "'")
tempList.append(norm)
else:
tempList.append(x)
return tempList
值添加到列表中而不用NULL
开头。 这属于'
函数。
createInsert()
但是我认为这些都不可行,因为它们会大大降低程序的速度(使用较大的文件会引发for x in tempMaster:
if x == 'NULL':
value = x
tempMaster.append(value)
else:
value = "'" + x + "'"
tempMaster.append(value)
values = map((lambda x: x.strip()), tempMaster)
printOut = insert + ' (' + ','.join(values) + ');')
outFile.write(printOut + '\n')
)。所以我问你的意见。如果这令人困惑或难以理解,我道歉。请让我知道我可以解决的问题,以便更容易理解是否是这种情况,并祝贺它到最后!
答案 0 :(得分:2)
而不是
values = map((lambda x: "'" + x.strip() + "'"), tempMaster)
把这个
values = map((lambda x: "'" + x.strip() + "'" if x!='NULL' else x), tempMaster)
for row in csvFile:
values = [] # creates the final list
insert = 'INSERT INTO ' + 'table_name' + ' (' + ','.join(master)+ ') VALUES ' # SQL syntax crap
for x in master:
try:
i = col.index(x) # looks for the value in the column list
r = row[i] # gets the row value at the same index as the found column
value.append("'"+r.strip()+"'") # appends the row value to the final list
except ValueError:
value.append('NULL') # if the value is not found in the column list it just appends the string to the row master list
然后你value
正确填充,节省内存和CPU。
答案 1 :(得分:0)
我检查了您的要求,我发现您的目录中有多个CSV。这些csv具有动态列。我的方法是创建所有列的静态列表
staticColumnList = ["ID","TableID","Number","Decimal","Letter","Random"]
现在,在读取文件时,请获取标题行,并为相应的列(如
)创建元组的临时列表 [(ID, column no in csv), (TableID, 'A' - File Name), (Number, column no in csv) etc...]
如果csv中没有列,则将x放在("Letter", x)
之内。现在,每行都创建一个循环并分配或选择这样的值: -
wholeDataList = []
rowList = []
for column in staticColumnList:
if int of type(column[1]):
rowList.append("'"+str(rowCSV[column[1]])+"'")
elif 'X' == column[1]:
rowList.append('null')
else:
rowList.append("'"+column[1]+"'")
wholeDataList.append("("+",".join(rowList)+")")
最后你有准备好的陈述,如下: -
qry = "INSERT into .. ("+",".join(staticColumnList)+") values " + ",".join(wholeDataList)