我将数据存储在多个文件夹中的CSV文件中,我想在Ubuntu系统上使用MySQL加载到多个SQL表中。每个表和文件都遵循此模式(文件没有id字段):
+ ------ + -------- + -------- + --------- + ---------- +
| SPO_Id | SPO_Name | SPO_Date | SPO_Price | SPO_Amount |
+ ------ + -------- + -------- + --------- + ---------- +
每个文件包含一天的定价和销售数据。不幸的是,这些文件的日期并未命名;它们存储在以日期命名的文件夹中。这是目录的示例图
------> 20170102 ------> prices.csv
/
/
Exmpl ------> 20170213 ------> prices.csv
\
\
------> 20170308 ------> prices.csv
这是我写的一个查询,它从文件中提取数据并将其存储到表中:
use pricing ; # the database I want the tables in
drop table if exists SP_2017_01_02 ;
create table SP_2017_01_02 (
SPO_Id int not null primary key auto_increment,
SPO_Name varchar(32),
SPO_Date date,
SPO_Price float,
SPO_Amount int
);
load data local infile '/Exmpl/20170102/prices.csv'
into table SP_2017_01_02
fields terminated by ','
lines terminated by '\n'
ignore 1 lines # First line contains field name information
(SPO_Name, SPO_Date, SPO_Price, SPO_Amount) ;
select * from SP_2017_01_02 ;
show tables ;
此查询适用于一次加载一个表;但是,因为我有数百个表,所以我需要自动化这个过程。我环顾四周,这里有一些我发现的东西:
Here是一个类似于我的问题,只有这个问题引用了SQL Server。答案给出了一个没有任何实质内容的建议。
This question也非常类似于我的,只有这是专门使用SSIS,我无法访问(并且问题没有得到答复)
This post建议使用控制文件引用,但这适用于sql-loader和oracle。
Using python可能是要走的路,但我以前从未使用它,我的问题似乎太复杂了,无法启动。
This one和this one也使用python,但它们只是用一个文件中的数据更新一个表。
我在SQL Server上做了很多工作,但我对MySQL很新。非常感谢任何帮助!
更新
我试图在MySQL中使用Dynamic SQL来做到这一点。遗憾的是,MySQL需要使用存储过程来执行动态SQL,但它不允许在存储过程中使用加载数据函数。作为@RandomSeed pointed out,this cannot be done只有MySQL。我将接受他的建议,并尝试编写一个shell / python脚本来处理这个问题。
我会把这个问题保持开放,直到我(或其他人)能够得出一个可靠的答案。
答案 0 :(得分:1)
所以一旦你有一个sql查询/函数/脚本读取一个表,它看起来像你做的那样(或者可以在python中简单地构建一个等价的表),使用python循环遍历目录结构并获取文件名很简单。如果你每次都可以以某种方式传递infile '/Exmpl/20170102/prices.csv'
一个新的csv参数,并在python中调用你的sql脚本,你应该是好的。
我现在没有太多时间,但我想告诉你如何使用python获取这些文件名字符串。
import os
prices_csvs = []
for root, dirs, files in os.walk(os.path.join('insert_path_here', 'Exmpl'):
for f in files:
if f == 'prices.csv':
prices_csvs.append(os.path.join(root, f))
break # optional, use if there only is one prices.csv in each subfolder
for csv_file in prices_csvs:
# csv_file is a string of the path for each prices.csv
# if you can insert it as the `infile` parameter and run the sql, you are done
# admittedly, i don't know how to do this at the moment
os.walk
遍历每个子目录,将名称root
提供给该文件夹的路径,将所有目录列为dirs
,将文件列为files
。从那里可以很简单地检查文件名是否与您要查找的文件匹配,并将其存储在列表中(如果有)。循环遍历列表会产生包含Exmpl中每个prices.csv路径的字符串。
希望能够对python如何提供帮助有所了解
答案 1 :(得分:1)
我已将查理的答案标记为正确的答案,因为虽然他没有完全回答这个问题,但他给了我一个很好的开始。以下是可能想要了解如何将csv文件加载到MySQL的任何人的代码。基本思想是在Python中动态构造一个字符串,然后在MySQL中执行该字符串。
#!/usr/bin/python
import os
import MySQLdb # Use this module in order to interact with SQL
# Find all the file names located in this directory
prices_csvs = []
for root, dirs, files in os.walk(os.path.join('insert_path_here', 'Exmpl'):
for f in files:
if f == 'prices.csv':
prices_csvs.append(os.path.join(root, f))
break
# Connect to the MySQL database
db = MySQLdb.connect(host ="<Enter Host Here>", user = "<Enter User here>", passwd = "<Enter Password Here>", db = "<Enter Database name here>" )
# must create cursor object
cur = db.cursor()
for csv_file in prices_csvs:
directory = "'" + csv_file + "'"
table = csv_file[56:64] # This extracts the name of the table from the directory
sql_string1 = "drop table if exists SD" + table + " ;\n"
sql_string2 = "create table SD" + table + " as \n\
<Enter your fields here> \n\
); \n"
sql_string3 = "load data local infile " + directory + " \n\
into table TempPrices \n\
fields terminated by ',' \n\
lines terminated by " + repr('\n') + " \n\
ignore 1 lines ;\n"
# Print out the strings for debugging
print sql_string1
print sql_string2
print sql_string3
print sql_string4
print sql_string5
# Execute your SQL statements
cur.execute(sql_string1)
cur.execute(sql_string2)
cur.execute(sql_string3)
cur.execute(sql_string4)
cur.execute(sql_string5)
db.commit()
db.close()
在调试时,我发现复制打印的SQL语句并将其粘贴到MySQL中以确认字符串是否已成功构建非常有用。