【问题标题】:python sqlite insert named parameters or nullpython sqlite插入命名参数或null
【发布时间】:2013-06-14 17:06:22
【问题描述】:

我正在尝试使用命名参数将字典中的数据插入数据库。我有一个简单的 SQL 语句,例如

SQL = "INSERT INTO status (location, arrival, departure) VALUES (:location, :arrival,:departure)"
dict = {'location': 'somewhere', 'arrival': '1000', 'departure': '1001'}
c.execute(SQL,dict)

在某个位置插入某个位置,1000 插入到到达列,1001 插入到离开列。

我实际拥有的数据将包含位置,但可能包含到达或出发,但可能不包含两者(在这种情况下,表中没有任何内容或 NULL 可以进入)。在这种情况下,我得到 sqlite3.ProgrammingError: You did not provide a value for binding 2.

我可以通过使用 defaultdict 来解决这个问题:

c.execute(SQL,defaultdict(str,dict))

为了让事情稍微复杂一些,我实际上将有一个字典列表,其中包含多个到达或离开的位置。

    ({'location': 'place1', 'departure': '1000'},
    {'location': 'palce2', 'arrival': '1010'},
    {'location': 'place2', 'departure': '1001'})

我希望能够使用 c.executemany 运行它,但是我现在不能使用 defaultdict。

我可以遍历列表中的每个字典并运行许多 c.execute 语句,但 executemany 似乎是一种更简洁的方法。

为方便起见,我简化了这个示例,实际数据在字典中有更多条目,并且我从 JSON 文本文件构建它。

有人对我如何做到这一点有任何建议吗?

【问题讨论】:

    标签: python sqlite named-parameters


    【解决方案1】:

    使用None 插入NULL

    dict = {'location': 'somewhere', 'arrival': '1000', 'departure': None}
    

    您可以使用默认字典和生成器将其与executemany() 一起使用:

    defaults = {'location': '', 'arrival': None, 'departure': None}
    
    c.executemany(SQL, ({k: d.get(k, defaults[k]) for k in defaults} for d in your_list_of_dictionaries)
    

    【讨论】:

    • 谢谢马丁 - 这行得通。对于遇到此问题的任何其他人,默认字典需要包含每个可能项目的条目,即使实际字典将始终具有它。此外,executemany 行上缺少最后一个右括号。
    【解决方案2】:

    这个问题有一个更简单的解决方案,在大多数情况下应该是可行的; 只需传递给 executemany 列表 defaultdict 而不是 dict列表。

    换句话说,如果您从头开始将行构建为defaultdict,您可以将defaultdict 行的列表直接传递给命令executemany,而不是将它们构建为字典,然后在使用@ 之前修补情况987654327@.

    以下工作示例 (Python 3.4.3) 说明了这一点:

    import sqlite3
    from collections import defaultdict
    # initialization
    db = sqlite3.connect(':memory:')
    c = db.cursor()
    c.execute("CREATE TABLE status(location TEXT, arrival TEXT, departure TEXT)")
    SQL = "INSERT INTO status VALUES (:location, :arrival, :departure)"
    # build each row as a defaultdict
    f = lambda:None # use str if you prefer
    row1 = defaultdict(f,{'location':'place1', 'departure':'1000'})
    row2 = defaultdict(f,{'location':'place2', 'arrival':'1010'})
    rows = (row1, row2)
    # insert rows, executemany can be safely used without additional code
    c.executemany(SQL, rows)
    db.commit()
    # print result
    c.execute("SELECT * FROM status")
    print(list(zip(*c.description))[0])
    for r in c.fetchall():
        print(r)
    db.close()
    

    如果你运行它,它会打印:

    ('location', 'arrival', 'departure')
    ('place1', None, '1000') # None in Python maps to NULL in sqlite3
    ('place2', '1010', None)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-10
      • 2015-03-27
      • 1970-01-01
      • 2012-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-15
      相关资源
      最近更新 更多