programing

PostgreSQL: JSON 열에서 특성 제거

magicmemo 2023. 4. 6. 21:29
반응형

PostgreSQL: JSON 열에서 특성 제거

json 유형 열에서 일부 특성을 제거해야 합니다.

표:

CREATE TABLE my_table( id VARCHAR(80), data json);
INSERT INTO my_table (id, data) VALUES (
  'A', 
  '{"attrA":1,"attrB":true,"attrC":["a", "b", "c"]}'
);

그럼 이제 요.attrBdata.

alter table my_table drop column data->'attrB';좋을 것 같아요.하지만 임시 테이블이 있는 방법도 충분할 거예요.

업데이트: 9.5 이상의 경우 사용할 수 있는 명시적 연산자가 있습니다.jsonb(가) )jsoncolumn, 하여 수정을 할 수 있습니다 : typeed column, casts, casts, casts, casts, casts, casts, casts, casts, casts, casts, casts, column,

오브젝트를 삭제하는 은, JSON 「(」( 「」)를 할 수 .-★★★★★★★★★★★★★★★★★★:

SELECT jsonb '{"a":1,"b":2}' - 'a', -- will yield jsonb '{"b":2}'
       jsonb '["a",1,"b",2]' - 1    -- will yield jsonb '["a","b",2]'

JSON을 할 수 .#-★★★★★★★★★★★★★★★★★★:

SELECT '{"a":[null,{"b":[3.14]}]}' #- '{a,1,b,0}'
-- will yield jsonb '{"a":[null,{"b":[]}]}'

원래 의 수정 할 수 을 집약하는 9.로 집약할 수 .json json_object_agg().

관련: Postgre의 기타 JSON 조작SQL:

원래 답변(Postgre에 적용)SQL 9.3):

"Postgre" "9. SQL 9.3 사용하여 할 수 .json_each()불필요한 필드를 필터링한 다음 수동으로 json을 다시 빌드합니다.예를 들어 다음과 같습니다.

SELECT data::text::json AS before,
       ('{' || array_to_string(array_agg(to_json(l.key) || ':' || l.value), ',') || '}')::json AS after
FROM (VALUES ('{"attrA":1,"attrB":true,"attrC":["a","b","c"]}'::json)) AS v(data),
LATERAL (SELECT * FROM json_each(data) WHERE "key" <> 'attrB') AS l
GROUP BY data::text

9.2(또는 그 이하)에서는 불가능합니다.

편집:

함수는 임의의 할 수 .아트리뷰트라고 합니다.json 추가:

편집 2:string_agg()이 싸다array_to_string(array_agg())

CREATE OR REPLACE FUNCTION "json_object_delete_keys"("json" json, VARIADIC "keys_to_delete" TEXT[])
  RETURNS json
  LANGUAGE sql
  IMMUTABLE
  STRICT
AS $function$
SELECT COALESCE(
  (SELECT ('{' || string_agg(to_json("key") || ':' || "value", ',') || '}')
   FROM json_each("json")
   WHERE "key" <> ALL ("keys_to_delete")),
  '{}'
)::json
$function$;

이 기능을 사용하면 아래 쿼리를 실행할 수 있습니다.

UPDATE my_table
SET data = json_object_delete_keys(data, 'attrB');

Postgre를 통해 이 작업이 훨씬 쉬워졌습니다.JSONB 유형을 사용하는 SQL 9.5.여기서 설명하는 JSONB 연산자를 참조하십시오.

"-" 연산자를 사용하여 최상위 속성을 제거할 수 있습니다.

SELECT '{"a": {"key":"value"}, "b": 2, "c": true}'::jsonb - 'a'
// -> {"b": 2, "c": true}

업데이트 콜 내에서 이 명령을 사용하여 기존 JSONB 필드를 업데이트할 수 있습니다.

UPDATE my_table SET data = data - 'attrB'

함수에서 사용되는 경우 매개변수를 통해 속성 이름을 동적으로 제공할 수도 있습니다.

CREATE OR REPLACE FUNCTION delete_mytable_data_key(
    _id integer,
    _key character varying)
  RETURNS void AS
$BODY$
BEGIN
    UPDATE my_table SET
        data = data - _key
    WHERE id = _id;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

역연산자는 2개의 JSONB 패킷을 연결하기 위한 "||"입니다.Atribute를 가장 오른쪽에서 사용하면 이전 Atribute가 덮어쓰게 됩니다.

SELECT '{"a": true, "c": true}'::jsonb || '{"a": false, "b": 2}'::jsonb 
// -> {"a": false, "b": 2, "c": true}

postgres의 과 같은 .이 문제를 해결할 수 있는 방법은-츠키다

UPDATE my_table
SET data = data::jsonb - 'attrB'
WHERE id = 'A';

SELECT '{"a": "b"}'::jsonb - 'a';.5.합니다. ★★★★★★★★★★★★★★.SELECT '{"a": "b"}'::jsonb #- '{a}';효과가 있었다!

간단히 .#-예를 들어 다음과 같습니다.

SELECT '{"foo": 10, "bar": [], "baz": {}}'::jsonb #- '{baz}';

다음과 같은 하위 필드를 제거하는 경우:

{
  "a": {
    "b": "REMOVE ME!"
  }
}

다음과 같이 간단하게 할 수 있습니다.

UPDATE my_table
SET my_json_column = my_json_column::jsonb #- '{a,b}';

이것은 jsonb 연산자를 사용하는 9.5+에서는 확실히 간단하지만, poz가 여러 키를 제거하기 위해 쓴 기능은 여전히 유용합니다.예를 들어 삭제할 키가 테이블에 저장되어 있는 경우 함수를 사용하여 모든 키를 제거할 수 있습니다.다음은 jsonb 및 postgresql 9.5+를 사용하여 업데이트된 기능입니다.

CREATE FUNCTION remove_multiple_keys(IN object jsonb, 
                                     variadic keys_to_delete text[], 
                                     OUT jsonb)
  IMMUTABLE
  STRICT
  LANGUAGE SQL
AS 
$$
  SELECT jsonb_object_agg(key, value)
     FROM (SELECT key, value 
           FROM jsonb_each("object")
           WHERE NOT (key = ANY("keys_to_delete")) 
     ) each_subselect
$$
;

삭제할 키가 테이블에 저장되어 있는 경우(예를 들어 "table_with_keys" 테이블의 "keys" 열) 이 함수를 다음과 같이 호출할 수 있습니다.

SELECT remove_multiple_keys(my_json_object, 
                            VARIADIC (SELECT array_agg(keys) FROM table_with_keys));

보기 흉한 해킹이지만attrB는 첫 번째 키가 아니며 한 번만 나타납니다.그 후 다음 작업을 수행할 수 있습니다.

UPDATE my_table SET data = REPLACE(data::text, ',"attrB":' || (data->'attrB')::text, '')::json;

다른 편리한 방법은 hstore 확장을 사용하는 것입니다.이렇게 하면 키를 설정/삭제할 수 있는 편리한 기능을 json 객체에 쓸 수 있습니다.같은 기능을 하기 위해 다음과 같은 기능을 생각해 냈습니다.

CREATE OR REPLACE FUNCTION remove_key(json_in json, key_name text)
 RETURNS json AS $$
 DECLARE item json;
 DECLARE fields hstore;
BEGIN
 -- Initialize the hstore with desired key being set to NULL
 fields := hstore(key_name,NULL);

 -- Parse through Input Json and push each key into hstore 
 FOR item IN  SELECT row_to_json(r.*) FROM json_each_text(json_in) AS r
 LOOP
   --RAISE NOTICE 'Parsing Item % %', item->>'key', item->>'value';
   fields := (fields::hstore || hstore(item->>'key', item->>'value'));
 END LOOP;
 --RAISE NOTICE 'Result %', hstore_to_json(fields);
 -- Remove the desired key from store
 fields := fields-key_name;

 RETURN hstore_to_json(fields);
END;
$$ LANGUAGE plpgsql
SECURITY DEFINER
STRICT;

간단한 사용 예는 다음과 같습니다.

SELECT remove_key(('{"Name":"My Name", "Items" :[{ "Id" : 1, "Name" : "Name 1"}, { "Id" : 2, "Name 2" : "Item2 Name"}]}')::json, 'Name');
-- Result
"{"Items": "[{ \"Id\" : 1, \"Name\" : \"Name 1\"}, { \"Id\" : 2, \"Name 2\" : \"Item2 Name\"}]"}"

set_key 조작과 함께 다음 기능을 수행합니다.

CREATE OR REPLACE FUNCTION set_key(json_in json, key_name text, key_value text)
RETURNS json AS $$
DECLARE item json;
DECLARE fields hstore;
BEGIN
 -- Initialize the hstore with desired key value
 fields := hstore(key_name,key_value);

 -- Parse through Input Json and push each key into hstore 
 FOR item IN  SELECT row_to_json(r.*) FROM json_each_text(json_in) AS r
 LOOP
   --RAISE NOTICE 'Parsing Item % %', item->>'key', item->>'value';
   fields := (fields::hstore || hstore(item->>'key', item->>'value'));
 END LOOP;
 --RAISE NOTICE 'Result %', hstore_to_json(fields);
 RETURN hstore_to_json(fields);
END;
$$ LANGUAGE plpgsql
SECURITY DEFINER
STRICT;

나는 여기 내 블로그에서 이것에 대해 더 많이 논의했다.

함수를 작성하지 않고 Postgres 9.4에서 json 키를 삭제하는 간단한 업데이트 쿼리를 찾느라 고생하고 있었습니다.@posz answer 업데이트입니다.

UPDATE someTable t
SET someField = newValue
FROM (
    SELECT id,
        json_object_agg(l.key, l.value)::text AS newValue
    FROM someTable t,
        LATERAL (
            SELECT *
            FROM json_each(t.someField::json)
            WHERE "key" <> ALL (ARRAY['key1', 'key2', 'key3'])
        ) AS l
    GROUP BY id
) upd
WHERE t.id = upd.id

쿼리에서는 다음과 같은 테이블이 있다고 가정합니다.

CREATE TABLE myTable (
    id SERIAL PRIMARY KEY,
    someField text
);

json_object_agg 행이 아닌 @posz answer 행에서 이 행을 사용하면 오래된 포스트그리어로 동작할 수 있을 것 같습니다만, 테스트하지 않았습니다.

('{' || array_to_string(array_agg(to_json(l.key) || ':' || l.value), ',') || '}')::json AS after

또한 select from subrequest를 실행하여 올바른 데이터를 업데이트하고 있는지 확인하십시오.

저 같은 경우에는

{"size": {"attribute_id": 60, "attribute_name": "Size", "attribute_nameae": "Size" "selected_option": {"option_id": 632, "option_name": "S"}}, "main_color": {"attribute_id": 61, "attribute_name": "Main Color", "selected_option": {"option_id": 643, "option_name": "Red"}}}

크기 삭제 -> 속성_nameae

UPDATE table_name set jsonb_column_name = jsonb_set(jsonb_column_name, '{size}', (jsonb_column_name->'size') -  'attribute_namea') WHERE <condition>

포스트그레용SQL version >9.6은 간단하게 실행할 수 있습니다.

UPDATE my_table 
set data = data::jsonb - 'attrB'

단일 문서뿐만 아니라 배열에서도 JSON 속성을 제거하려면 다음과 같은 문을 사용하십시오.

    UPDATE table_to_update t
    SET jsonColumnWithArray = (SELECT JSON_AGG(jsonItem)
               FROM (SELECT JSON_ARRAY_ELEMENTS(t1.jsonColumnWithArray)::JSONB #- '{customerChange, oldPeriod}' AS jsonItem
                     FROM table_to_update t1
                     WHERE t1.id = t1.id) AS t2);

입력

[
  {
    "customerChange": {
      "newPeriod": null,
      "oldPeriod": null
    }
  },
  {
    "customerChange": {
      "newPeriod": null,
      "oldPeriod": null
    }
  }
]

산출량

[
  {
    "customerChange": {
      "newPeriod": null
    }
  },
  {
    "customerChange": {
      "newPeriod": null
    }
  }
]

언급URL : https://stackoverflow.com/questions/23490965/postgresql-remove-attribute-from-json-column

반응형