将多个文件中的数据插入多个表中

时间:2017-03-29 21:52:43

标签: python mysql sql shell dynamic-sql

我将数据存储在多个文件夹中的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 onethis one也使用python,但它们只是用一个文件中的数据更新一个表。

我在SQL Server上做了很多工作,但我对MySQL很新。非常感谢任何帮助!

更新

我试图在MySQL中使用Dynamic SQL来做到这一点。遗憾的是,MySQL需要使用存储过程来执行动态SQL,但它不允许在存储过程中使用加载数据函数。作为@RandomSeed pointed outthis cannot be done只有MySQL。我将接受他的建议,并尝试编写一个shell / python脚本来处理这个问题。

我会把这个问题保持开放,直到我(或其他人)能够得出一个可靠的答案。

2 个答案:

答案 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中以确认字符串是否已成功构建非常有用。