如何从 PL/lpgSQL 函数内部获取记录(行)的 jsonb 数组的键和值

How to get keys and values of jsonb array for a record (row) from inside PL/lpgSQL function

我在 table 中有一个文本列,其中包含 city/country 类型的数据,可转换为 jsonb,例如:

SELECT 
        '{"Toronto":"Canada","Moscow":"Russia","New York":"USA"}'::text 
AS city_data

我必须将其转换为 JSONB 这种格式的数组:

[
    {
        "city": "Moscow",
        "match": false,
        "country": "Russia"
    },
    {
        "city": "Toronto",
        "match": false,
        "country": "Canada"
    },
    {
        "city": "New York",
        "match": false,
        "country": "USA"
    }
]

我可以在常规 PostgreSQL 查询中做到这一点,首先获取每个 key/value,然后将其聚合回 JSONB 数组。

WITH data AS (
    WITH city_table AS (
        SELECT 
        '{"Toronto":"Canada","Moscow":"Russia","New York":"USA"}'::text AS city_data
            )
    SELECT cities.key AS city, cities.value AS country
    FROM city_table
    LEFT JOIN jsonb_each_text(city_data::jsonb) cities ON true
              )
SELECT jsonb_agg(jsonb_build_object(
'city', city::text, 
'country', country::text, 
'match', false::boolean)) AS combined
FROM data

但我不知道如何在 PL/pgSQL 函数中执行此 LEFT JOIN。

函数在游标上循环,在满足某个条件的地方,我需要做这个转换并存储到一个变量中。

即在光标 cur 内,对于记录 rec,我必须得到相应的 rec.city_data,将其转换为新格式,并将其保存到变量 var_city_data

如何在 rec 上执行 LEFT JOIN?通常在记录中我只调用 rec.field_name 而不需要做任何 FROM...

我试过了:


FOR rec IN cur LOOP

        -- conditions........

        WITH data AS (
            SELECT cities.key AS city, cities.value AS country
            FROM rec -- I THINK THE ERROR IS SOMEWHERE HERE AND NEXT LINE
            LEFT JOIN jsonb_each_text(rec.city_data::jsonb) cities ON true
            )
        SELECT INTO var_city_data
        jsonb_agg(jsonb_build_object('city', city::text, 
                                    'country', country::text, 
                                    'match', false::boolean))
        FROM data;

        RAISE NOTICE 'city_data: %  ', var_city_data;

        -- ... other conditions...
END LOOP;

我也尝试删除 FROM rec ,直接执行 FROM jsonb_each_text(rec.city_data::jsonb) 等,但我不断收到 PL/pgSQL function inline_code_block.

类型的错误

如有任何帮助,我们将不胜感激。

注意:此函数必须在 PostgreSQL 9.6 和 11+ 版本上运行

不需要LEFT JOINWITH条款。

只需尝试以下查询:

FOR rec IN cur LOOP

        -- conditions........

SELECT jsonb_agg(jsonb_build_object(
'city', cities.key::text, 
'country', cities.value::text, 
'match', false::boolean)) 
INTO var_city_data
FROM jsonb_each_text(rec.city_data::jsonb) cities(key,value);
    
RAISE NOTICE 'city_data: %  ', var_city_data;

-- ... other conditions...
END LOOP;

DEMO