【问题标题】:Insert a list of dictionaries into an SQL table using python使用 python 将字典列表插入到 SQL 表中
【发布时间】:2016-02-11 16:43:02
【问题描述】:

我正在使用 python 和 sql 数据库迈出第一步,但仍然不确定要使用哪个包以及如何使用。我有一个包含大约 300k 字典的列表,每个字典大约有 20 个键。这些 dicts 应该被插入到一个 SQL 表中。

在我看来,dict 方法列表的优点是,我明确命名了要在其中输入特定值的列。 (可能,这不是一个好方法)

让我举一个更具体的例子来说明我的问题的本质。 该表由三列组成:ID(整数)、价格(十进制)、类型(字符串)。 类型支持空值。

我的字典的键名相同,字典列表可能如下所示:

lst = [{'ID':1, 'Price': '9.95', 'Type': None}, 
       {'ID':2, 'Price': '7.95', 'Type': 'Sports'}, 
       {'ID':3, 'Price': '4.95', 'Type': 'Tools'}, ...]

所以出现的问题如下:

  1. 使用 dicts 的方法是否正确? (请注意,我有 20 列)
  2. 如果是/或否:应该如何有效地执行这样的查询?
  3. 是否有必要在 SQL 语句之前将价格转换为十进制,或者这可以“即时”实现
  4. None 值是自动转换为 null,还是需要做额外的工作?

【问题讨论】:

  • 你在做什么样的项目?如果您使用 python 和数据库,那么实现像 Django 这样的 MVC 可能会有所帮助。 en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controllerdjangoproject.com
  • 我正在从网络抓取服务(几个 json 文件)中获取数据,并且需要提取我插入到 MSSQL-Server 中的信息
  • 我假设这是一次性的,因此实施整个框架并不是一个有用的建议。您使用的是哪种类型的 SQL?许多数据库支持各种格式的批量插入(这意味着将您的网络抓取数据写入文件可能更有用)。例如。 msdn.microsoft.com/en-CA/library/ms188609.aspx(编辑错误链接)
  • 我每周都这样做。服务器在 mssql 上运行。每周我都会收到大约 100 个文件,我需要对其进行预处理。只有一些(尽管大部分)数据应以该特定表结尾。此外,数据在服务器中后,我需要做一些实体解析,字符串匹配。然后,需要创建一个新的、干净的表

标签: python sql python-3.x


【解决方案1】:

假设您使用的是符合 Python Database API specification 的数据库驱动程序。

类型转换(问题 3 和 4)应由开箱即用的数据库驱动程序处理。

至于2),有executemany()

cursor.executemany("""
    INSERT INTO 
        mytable
        (id, price, type)
    VALUES
        (%(id)s, %(price)s, %(type)s)
""", lst)

【讨论】:

  • 因此,在您的解决方案中,您不会使用字典列表,而是使用元组列表。因此,您需要维护每个元组中的顺序,对吗?
  • hmm,所以字典没有排序在这里不是问题吗? (即 %(id) 指的是字典中的 ID 键等等?这个语句也会是一个准备好的语句吗?据我所知,在这种情况下需要指定 ? 作为占位符。由于大量查询,准备好的语句绝对是首选
  • @Quickbeam2k1 是的,顺序无关紧要。并且查询是参数化的 - 这意味着您在安全方面是安全的。
  • 所以我做了一些进一步的研究。对于 pymssql,目前没有可用的参数化查询。批量查询只是执行几个插入查询。对于 pyodbc,应该考虑 github 上的 issue #62。这似乎解决了当前在执行参数化查询的 pyodbc 中出现的一些性能问题(每列都重新准备了吗?),但我无法对其进行测试。所以我的数据集包含大约 400k 行和 30 列,并产生以下结果 pyodbc(3.0.10) -> ~ 900 秒,pyodbc(3.0.10)+sqlalchemy -> 730 秒,pymssql -> 270 秒。令人惊讶的是,pymssql 获胜
【解决方案2】:
mydb = MySQLdb.connect(host='',    # your host_name
                       user='',    # your username
                       passwd='',  # your password
                       db=''       # your database
                       )
cur= mydb.cursor()
insert_query = "INSERT INTO table_name(feild_1,feild2,feild3) VALUES ( %(id)s, %(price)s, %(type)s);"
cur.executemany(insert_query, lst)
mydb.commit

【讨论】:

    【解决方案3】:

    回答您的问题:

    • 使用字典列表没问题
    • 下面是处理您案件的完整应用程序
    • 没有必要将价格转换为十进制,在这个例子中,我们在 MySQL 中将价格声明为十进制,但在列表中,它被设置为字符串也为整数,但它保存为十进制
    • None 值自动转换为 null
    from tkinter import *
    import mysql.connector as myConnector
    from tkinter import messagebox
    from mysql.connector import Error
    def insert(table,lst):
    
        myList = listNestedDictForTblInsert(lst)
        print(myList)
        
        mySqlStr = f'INSERT INTO {table}(ID, Price, Type) VALUES(%s,%s,%s)' 
        val = myList
        print(mySqlStr)
        print(val)
        myDb = myConnector.connect(host='localhost',
                                   database = "libraryDb2",
                                   user='root',
                                   password='dhso')
        try:
           myCursor = myDb.cursor()
           myCursor.executemany(mySqlStr, val)
           myDb.commit()
           messagebox.showinfo("show info", "Data is saved successfully")
        except Error as e:
           messagebox.showinfo("show info", "Data is not saved")
    
        myDb.close()
        myCursor.close()
    
    
    def listNestedDictForTblInsert(data):
    #Convert the list of dictionaries into list of tuples
       myList = []
       for i in range(len(data)):
          myList1 = []
          for value in (data[i].values()):
             myList1.append(value)
          myList1 = tuple(myList1)   
          myList.append(myList1)
       return myList
    #Output myList:
    #[('Ralph', 45), ('Betty', 50), ('Joey', 45), ('Heather', 25)]
               
    root = Tk()
    
    lst = [{'ID':1, 'price': 9.95, 'type': None}, 
           {'ID':2, 'Price': '7', 'type': 'Sports'}, 
           {'ID':3, 'Price': 4, 'Type': 'Tools'}]
    table = 'test1'
    root.title("Testing Part")
    btn = Button(root, text = "Insert Dictionary in MYSQL Table", width = 30, command = lambda : insert(table, lst))
    btn.pack()
    root.mainloop
    
    

    【讨论】:

      猜你喜欢
      • 2022-10-18
      • 2021-07-04
      • 1970-01-01
      • 1970-01-01
      • 2013-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-27
      相关资源
      最近更新 更多