从 psycopg2 在 Postgres 中插入 dict 列表作为 json 数组

Posted

技术标签:

【中文标题】从 psycopg2 在 Postgres 中插入 dict 列表作为 json 数组【英文标题】:Inserting list of dict as json array in Postgres from psycopg2 【发布时间】:2021-05-23 17:22:57 【问题描述】:

我在 postgres 中有这张表

CREATE TABLE target (
    a json
)

我想使用 psycopg2 向其中插入数据

import psycopg2
import psycopg2.extras as extras

# a is list of list of dicts
a = [['a':1,'b':2, 'd':3,'e':2],
      ['a':3,'b':1, 'e':2,'f':6]]

# convert a to list of tuples containing extras.Json objects
a = [(extras.Json(x),) for x in a]

# insert a to the database
query = ('WITH ins (a) AS '
         '(VALUES %s) '
         'INSERT INTO target (a) '
         'SELECT ins.a '
         'FROM ins;')

cursor = conn.cursor()

extras.execute_values(cursor, query, a)

但是我得到了错误:column "a" is of type json but expression is of type text

这个例子被简化以使问题更清楚(这就是为什么这个例子使用WITH ins 语句,因为我需要将一个表加入它。我原以为这应该可以工作,但由于某种原因它没有' t. 我的怀疑是问题是我先将它加载到 ins 中,并且由于某种原因默认情况下它可能将其加载为文本而不是 json。

我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

类似这样的:

CREATE TABLE target (
    a json
)

query = "INSERT INTO target VALUES %s"  

b = [[extras.Json(row)] for row in a] 
cur = con.cursor()
extras.execute_values(cur, query, b)
con.commit()

select * from target;
                  a                   
--------------------------------------
 ["a": 1, "b": 2, "d": 3, "e": 2]
 ["a": 3, "b": 1, "e": 2, "f": 6]

直接从输入值简化为 INSERT。我将它们创建为列表,因为execute_values 可以采用序列序列或字典序列(如果使用命名参数)。

更新:

query = ('WITH ins (a) AS '
         '(VALUES %s) '
         'INSERT INTO target (a) '
         'SELECT ins.a::json '
         'FROM ins;')


【讨论】:

非常感谢您的回答。不幸的是,WITH ins 语句是必要的,因为我需要将一个表加入它。也许我过于简单化了。无论如何调整你的方法来工作WITH ins ... 我是否正确假设此解决方案会将 json 作为文本加载到 ins 中,然后在选择时将其从文本转换为 json? 是的,就是这样。

以上是关于从 psycopg2 在 Postgres 中插入 dict 列表作为 json 数组的主要内容,如果未能解决你的问题,请参考以下文章

Python/postgres/psycopg2:获取刚刚插入的行的 ID

psycopg2 无法插入特定列

Psycopg2 使用占位符插入表格

如何使用Flask,SQLAlchemy或psycopg2从Postgres中的光标获取数据

使用 psycopg2 调用 postgres 存储过程 - 无效的事务终止

用户 postgres 的 Psycopg2 对等身份验证