【问题标题】:Only inserting specific rows from csv file into Sqlite3 database using python仅使用 python 将 csv 文件中的特定行插入 Sqlite3 数据库
【发布时间】:2013-12-09 12:28:17
【问题描述】:

我正在尝试将 csv 文件导入到我正在使用 python 编写的 sqlite3 数据库中。我对以这种方式导入数据和一般的 sqlite3 还是很陌生。

我得到的数据文件的开头往往格式不规则,但我想要的行总是以日期字段 (dd/mm/yy) 和时间字段 (hh:mm:ss) 开头。 示例文件如下:

Hello I am a file, , , ,
I am a type of csv file, , , ,
Date, Time, ID number, Message
12/12/2012, 13:12:13, 1, Hello World
13/12/2012, 13:12:13, 2, Goodbye

所以我只想导入第 4 行和第 5 行(以及所有带有日期的后续行),但跳过描述文件和列标题的前 3 行。

到目前为止,我已经获得了读取数据然后将其与唯一标识符 (logID) 一起放入表中的代码,但目前我只是从第 4 行开始读取 - 我想要对于文件没有前 3 行简介的情况的更通用的解决方案。

#code above here opens the database and creates a cursor
with open(file) as csvfile:
    reader = csv.reader(csvfile, dialect='excel')
    for row in reader:
        if reader.line_num >= 4:
            values = logID + str(row[0]) + str(row[1]) + str(row[2]) + str(row[3])
            cursor.execute("INSERT INTO table VALUES(" +values+ ");")

提前感谢您的帮助!

【问题讨论】:

    标签: python csv sqlite


    【解决方案1】:

    尝试将row 中的第一项转换为Python datetime.datetime 对象。如果有效,则处理该行,如果无效,则通过循环处理continue

    import datetime as DT
    with open(file, 'rb') as csvfile:
        reader = csv.reader(csvfile, dialect='excel')
        for row in reader:
            try:
                date = DT.datetime.strptime(row[0], '%m/%d/%Y')
            except ValueError:
                continue 
        args = [logID] + row  
        sql = "INSERT INTO table VALUES ({})".format(', '.join(['?']*len(args)))
        cursor.execute(sql, args)
    

    以上内容适用于中小型 CSV。如果您有一个巨大的 CSV 文件,每行调用一次 cursor.execute 可能会很慢。为了提高性能,一次读取一大块(比如 1000 行),并将要插入的值累积到列表列表中,manyargs。然后调用

    cursor.executemany("INSERT INTO table VALUES(?,?,?,?,?)", manyargs)
    

    每块一次。


    顺便说一下,用字符串格式构造SQL命令如:

    cursor.execute("INSERT INTO table VALUES(" +values+ ");")
    

    可能存在安全风险。恶意构造的 CSV 文件可以利用这一行来运行任意 SQL 命令(参见SQL injectionLittle Bobby Tables)。为了防止这种情况,请使用参数化 SQL:

    cursor.execute("INSERT INTO table VALUES(?,?,?,?,?)", args)
    

    ? 是一个地标——每个字段值都有一个地标。 args 是一个包含您希望插入的值的序列(例如元组或列表)。请注意,args 作为第二个参数传递给cursor.execute。您不必将args 中的值转换为字符串(尽管在这种情况下,它们是字符串,因为csv.reader 产生字符串列表)。 sqlite3 模块将为您处理参数的引用。

    【讨论】:

    • 感谢您的帮助 - 我在其他解决方案中发现了日期时间转换,但不知道如何实现它。我希望该软件能够为具有不同列数的不同表传递数据。我还能使用参数化 SQL,还是必须能够定义“?”的数量?在声明中?
    • 我已经修改了上面的代码来展示如何处理任意数量的列。
    猜你喜欢
    • 2011-02-22
    • 2022-11-29
    • 1970-01-01
    • 2014-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多