Postgresql 使用psql脚本将jsonb逗号分隔值转换为json对象

Postgresql 使用psql脚本将jsonb逗号分隔值转换为json对象,postgresql,sql-update,jsonb,Postgresql,Sql Update,Jsonb,我在postgresql中有一个表,它有两列: Table "schemaname.tablename" Column | Type | Collation | Nullable | Default --------+-------------------+-----------+----------+--------- _key | character varying | | not null | value

我在postgresql中有一个表,它有两列:

               Table "schemaname.tablename"
 Column |       Type        | Collation | Nullable | Default
--------+-------------------+-----------+----------+---------
 _key   | character varying |           | not null |
 value  | jsonb             |           |          |
Indexes:
    "tablename_pkey" PRIMARY KEY, btree (_key)
我想转换jsonb的嵌套属性值,如下所示:

{
    "somekey": "[k1=v1, k2=v2, k3=v2]",
}
为此:

{
    "somekey":  [
        "java.util.LinkedHashMap",
        {
            "k1": "v1",
            "k2": "v2",
            "k3": "v3"
        }
    ]
}
我已经成功地将逗号分隔的字符串解析为字符串数组,但是除了必须对“=”应用另一个拆分之外,我真的不知道如何对表的所有行进行实际更新,并为somekey生成正确的jsonb值

select regexp_split_to_array(RTRIM(LTRIM(value->>'somekey','['),']'),',') from schemaname.tablename;

有什么想法吗?

试试这一个独立的测试数据:

使用tablename _键,值为 价值观 '测试','{somekey:[k1=v1,k2=v2,k3=v2]}'::jsonb, 'second','{somekey:[noone=不想,see=me,带垃圾]}'::jsonb, “第三个”,“{somekey:[some,key=with a=in其值,some=more here]}”:jsonb 选择 选项卡。\u键, jsonb_插件 “{somekey:[java.util.LinkedHashMap]}”,基本JSON结构 “{somekey,0}”,-要在后面插入的路径 jsonb_对象-从键值数组动态创建jsonb对象 数组\u aggkey\u值-将所有键值行聚合到一个数组中 , true-我们希望在匹配元素之后插入,而不是在它之前 随着你的转变 从…起 tablename作为选项卡, -以下是基于上一表的eahc行的隐式横向联接函数 regexp_匹配-生成多行 btrimtab.value->>'somekey','[]',-如您开始时所述 '\w[^=]*=[^,]*',-为键和值定义正则表达式组 “g”-我们需要所有键值集 作为关键值 按1分组 ; …导致:

  _key  |                                           json_transformed                                            
--------+-------------------------------------------------------------------------------------------------------
 second | {"somekey": ["java.util.LinkedHashMap", {"see": "me", "no one": "wants to"}]}
 third  | {"somekey": ["java.util.LinkedHashMap", {"some": "more here", "some,key": "with a = in it's value"}]}
 test   | {"somekey": ["java.util.LinkedHashMap", {"k1": "v1", "k2": "v2", "k3": "v2"}]}
(3 rows)
我希望内联注释能够足够详细地解释它是如何工作的

无需通过以下方式进行汇总/分组: 以下内容不需要分组,因为我们不需要聚合函数数组_agg,但对键值格式的要求稍低一些,并且由于某些数据的原因,会很容易中断查询。前面的变体只会删除一些键值:

使用tablename _键,值为 价值观 '测试','{somekey:[k1=v1,k2=v2,k3=v2]}'::jsonb, 'second','{somekey:[没有人想要,see=me,带垃圾]}'::jsonb 选择 _钥匙, jsonb_插件 “{somekey:[java.util.LinkedHashMap]}”,基本JSON结构 “{somekey,0}”,-要在后面插入的路径 jsonb_对象-从键值数组动态创建jsonb对象 键值-使用函数将键+值作为拆分 , true-我们希望在匹配元素之后插入,而不是在它之前 随着你的转变 从…起 tablename作为选项卡, -以下是基于上一表的eahc行的隐式横向联接函数 regexp_split_to_array-生成数组或键和值:[k,v,k,v,…] btrimtab.value->>'somekey','[]',-如您开始时所述 '=|,\s*'-regex匹配两个分隔符 作为关键值 ; …结果包括:

  _key  |                                json_transformed                                
--------+--------------------------------------------------------------------------------
 test   | {"somekey": ["java.util.LinkedHashMap", {"k1": "v1", "k2": "v2", "k3": "v2"}]}
 second | {"somekey": ["java.util.LinkedHashMap", {"see": "me", "no one": "wants to"}]}
(2 rows)
在第二行之前或在第三行之前的值中使用=字符向其提供垃圾将导致以下错误:

ERROR:  array must have even number of elements

这是非常有用的@Ancoron!我现在面临两个问题。一个小问题与正则表达式不支持多个关键字/值相关,另一个大问题是,如果删除WHERE子句,这段代码会将所有关键字/值合并到一行中,我需要每行生成一个json对象。第二个问题我想可以通过使用group by_keyI see来解决。我刚刚看了第二眼,您最初的想法是使用regexp\u split\u to\u数组,在这里可能会更好,但前提是没有键或值包含字符,或者=。否则,我们可能需要自己编写一个小助手函数。我将使用第二个选项更新我的解决方案。我还研究了现有的解析器,例如hstore,但它们的灵活性越来越差,也需要预处理。因此,在纯SQL中,使用regexp_匹配项的重写选项看起来是目前最好的方法。