【问题标题】:Psycopg2 insert python dictionary in postgres databasePsycopg2 在 postgres 数据库中插入 python 字典
【发布时间】:2016-08-29 09:39:53
【问题描述】:

在 python 3+ 中,我想将字典(或 pandas 数据框)中的值插入数据库。我选择了带有 postgres 数据库的 psycopg2。

问题是我无法找出正确的方法来做到这一点。我可以轻松地连接要执行的 SQL 字符串,但 psycopg2 文档明确警告不要这样做。理想情况下,我想做这样的事情:

cur.execute("INSERT INTO table VALUES (%s);", dict_data)

并希望执行可以找出字典的键与表中的列匹配。这没有用。从 psycopg2 文档的示例中我得到了这种方法

cur.execute("INSERT INTO table (" + ", ".join(dict_data.keys()) + ") VALUES (" + ", ".join(["%s" for pair in dict_data]) + ");", dict_data)

我从中得到了一个

TypeError: 'dict' object does not support indexing

将字典插入具有匹配列名的表中最自然的方法是什么?

【问题讨论】:

    标签: postgresql python-3.x dictionary psycopg2


    【解决方案1】:

    两种解决方案:

    d = {'k1': 'v1', 'k2': 'v2'}
    
    insert = 'insert into table (%s) values %s'
    l = [(c, v) for c, v in d.items()]
    columns = ','.join([t[0] for t in l])
    values = tuple([t[1] for t in l])
    cursor = conn.cursor()
    print cursor.mogrify(insert, ([AsIs(columns)] + [values]))
    
    keys = d.keys()
    columns = ','.join(keys)
    values = ','.join(['%({})s'.format(k) for k in keys])
    insert = 'insert into table ({0}) values ({1})'.format(columns, values)
    print cursor.mogrify(insert, d)
    

    输出:

    insert into table (k2,k1) values ('v2', 'v1')
    insert into table (k2,k1) values ('v2','v1')
    

    【讨论】:

    • 这与建议的 sql 的优缺点?第二种解决方案与建议的解决方案基本相同(字符串格式与复合除外)?如果需要,Afaik cur.execute 调用 cur.mogrify?
    • 已经有一段时间了,但我认为这段代码容易受到SQL注入攻击。
    【解决方案2】:

    我有时会遇到这个问题,尤其是关于 JSON 数据,我自然想将其作为 dict 处理。非常相似。 . .但也许更具可读性?

    def do_insert(rec: dict):
        cols = rec.keys()
        cols_str = ','.join(cols)
        vals = [ rec[k] for k in cols ]
        vals_str = ','.join( ['%s' for i in range(len(vals))] ) 
        sql_str = """INSERT INTO some_table ({}) VALUES ({})""".format(cols_str, vals_str)
        cur.execute(sql_str, vals)
    

    我通常从迭代器内部调用这种类型的东西,并且通常包装在 try/except 中。游标 (cur) 已经在外部范围中定义,或者可以修改函数签名并传入游标实例。我很少只插入一行。 . .和其他解决方案一样,如果底层架构也允许,这允许丢失列/值。只要在插入时不修改键视图底层的字典,就无需按名称指定键,因为值将按照键视图中的顺序排列。

    【讨论】:

      【解决方案3】:

      [建议的答案/解决方法 - 感谢您提供更好的答案!]

      经过一些试验/错误后,我得到了以下工作:

      sql = "INSERT INTO table (" + ", ".join(dict_data.keys()) + ") VALUES (" + ", ".join(["%("+k+")s" for k in dict_data]) + ");"
      

      这给出了 sql 字符串

      "INSERT INTO table (k1, k2, ... , kn) VALUES (%(k1)s, %(k2)s, ... , %(kn)s);"
      

      可能会被执行

      with psycopg2.connect(database='deepenergy') as con:
          with con.cursor() as cur:
              cur.execute(sql, dict_data)
      

      帖子/缺点?

      【讨论】:

      • 不确定为什么我会收到以下错误:(psycopg2.errors.SyntaxError) 在“%”第 1 行或附近出现语法错误:...1,响应,duration_time) VALUES (%(id )s, %(... sql insert 语句格式正确: INSERT INTO table (id, name, response, duration_time) VALUES (%(id)s, %(name)s, %(response)s, %( duration_time)s); 但是,当我执行 SQL 语句 cursor.execute(sql_insert, data_dict) 时,您是否知道问题出在哪里?
      【解决方案4】:

      使用 %(name)s 占位符可能会解决问题:

      dict_data = {'key1':val1, 'key2':val2}
      
      cur.execute("""INSERT INTO table (field1, field2) 
      VALUES (%(key1)s, %(key2)s);""", 
      dict_data)
      

      你可以在 psycopg2 doc Passing parameters to SQL queries找到用法

      【讨论】:

        【解决方案5】:

        这是另一种直接插入字典的解决方案

        产品型号(具有以下数据库列)

        name
        description
        price
        image
        digital - (defaults to False)
        quantity
        created_at - (defaults to current date)
        

        解决方案

            data = {
                "name": "product_name",
                "description": "product_description",
                "price": 1,
                "image": "https",
                "quantity": 2,
            }
            cur = conn.cursor()
            cur.execute(
                "INSERT INTO products (name,description,price,image,quantity) "
                "VALUES(%(name)s, %(description)s, %(price)s, %(image)s, %(quantity)s)", data
            )
        
            conn.commit()
            conn.close()
        

        注意:要插入的列在execute语句.. INTO products (column names to be filled) VALUES ..., data <- the dictionary (should be the same **ORDER** of keys)中指定

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-06-10
          • 1970-01-01
          • 1970-01-01
          • 2020-09-03
          • 1970-01-01
          • 1970-01-01
          • 2021-03-03
          • 2021-11-16
          相关资源
          最近更新 更多