如何在SQL中保留特定字符串以替换特定字符串之后仅替换字符串的一部分?

我有一个名为user的表,其中包含列数据。数据包含非常长的字符串(这是一个作为字符串嵌套在data列中的JSON)。在fontSize值为字符串的所有情况下,我想将 fontSize 键的所有值更改为int值,但必须保留int值。 所以基本上这就是我想要做的:

{
  "id": 1,"name": "New Window","resources": {
    "widgets": [
      {
        "id": 1,"color": "#ffffff","fontSize": "5","width": 150
      },{
        "id": 2,"color": "#aaaaaa","fontSize": "10","width": 200
      }
    ]
  }
}

更改为:

{
  "id": 1,"fontSize": 5,"fontSize": 10,"width": 200
      }
    ]
  }
}

在所有fontSize值是字符串的情况下(在某些情况下,它已经是整数)。 fontsize的值不同,必须保留它们。

我知道逻辑。我必须在表用户中找到所有情况,例如'%“ fontSize”:“%'之类的数据列,然后在” fontSize“:pattern之后删除第一个”,在数字之后删除第一个“。如何做到这一点?在SQL中是可能的?谢谢您的帮助!

HELLO_JAVA521 回答:如何在SQL中保留特定字符串以替换特定字符串之后仅替换字符串的一部分?

这非常丑陋,并显示了一个用例,其中使用JSON对模型进行规范化是一个错误的选择(如果那是正确的一对多关系,则列font_size将被定义为整数) ,那么您就不会遇到这个问题了。


我唯一能想到的就是取消所有数组元素的嵌套,将值更改为整数,将“小部件”聚合回数组,并使用它来更新表。

以下代码假定您的表中有一个名为id的主键列。

第一步是将fontSize值替换为适当的整数。

select t.id,jsonb_set(w.jw,'{fontSize}',to_jsonb((w.jw ->> 'fontSize')::int))
from the_table t
  cross join jsonb_array_elements(t.the_value -> 'resources' -> 'widgets') as w(jw)

jsonb_array_elements()将每个小部件作为单个JSONB值(在单独的行中)返回。 to_jsonb((w.jw ->> 'fontSize')::int将键fontSize的当前值转换为整数,jsonb_set()将其放回JSON值。

给出返回的示例数据(包括假定的主键列)

id | jsonb_set                                                  
---+------------------------------------------------------------
42 | {"id": 1,"color": "#ffffff","width": 150,"fontSize": 5} 
42 | {"id": 2,"color": "#aaaaaa","width": 200,"fontSize": 10}

现在可以将其聚合回一个数组:

select t.id,jsonb_agg(jsonb_set(w.jw,to_jsonb((w.jw ->> 'fontSize')::int))) as new_widgets
from the_table t
  cross join jsonb_array_elements(t.the_value -> 'resources' -> 'widgets') as w(jw)
group by id

鉴于上述示例日期,现在返回:

id | new_widgets                                                                                                               
---+---------------------------------------------------------------------------------------------------------------------------
42 | [{"id": 1,"fontSize": 5},{"id": 2,"fontSize": 10}] 

此查询现在可以用作UPDATE语句的源,该语句再次使用jsonb_set()来更改表中的值。

update the_table
  set the_value = jsonb_set(the_value,'{resources,widgets}',x.new_widgets)
from (  
  select t.id,to_jsonb((w.jw ->> 'fontSize')::int))) as new_widgets
  from the_table t
    cross join jsonb_array_elements(t.the_value -> 'resources' -> 'widgets') as w(jw)
  group by id
) as x
where x.id = the_table.id;

完整的在线示例:https://rextester.com/OIFOBX92774


如果您的列未定义为jsonb(应为该列),则需要在上述查询中将其强制转换为the_column::jsonb

本文链接:https://www.f2er.com/3139410.html

大家都在问