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"]}'
);
ここで、attrB
列からdata
を削除する必要があります。
何かのようなもの alter table my_table drop column data->'attrB';
いいだろう。しかし、一時テーブルを使用する方法でも十分です。
Update:9.5+には、jsonb
で使用できる明示的な演算子があります(json
が入力されている場合列、キャストを使用して変更を適用できます):
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.4では、元の回答(下記)の修正バージョンを使用できますが、JSON文字列を集約する代わりに、json_object_agg()
を使用してjson
オブジェクトに直接集約できます。
関連:PostgreSQL内でのその他のJSON操作:
元の回答(PostgreSQL 9.3に適用):
少なくともPostgreSQL 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
フィールドの任意の数の属性を削除できる関数を作成することです。
Edit 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');
_
JSONBタイプを使用するPostgreSQL 9.5では、これがはるかに簡単になりました。ドキュメント化されたJSONB演算子 here を参照してください。
「-」演算子を使用して、最上位の属性を削除できます。
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パケットを連結するための逆演算子は「||」です。属性を右端で使用すると、以前の属性が上書きされることに注意してください。
SELECT '{"a": true, "c": true}'::jsonb || '{"a": false, "b": 2}'::jsonb
// -> {"a": false, "b": 2, "c": true}
これはugいハックですが、attrB
が最初のキーではなく、一度しか表示されない場合は、次のことができます。
UPDATE my_table SET data = REPLACE(data::text, ',"attrB":' || (data->'attrB')::text, '')::json;
9.5+ではjsonb演算子を使用する方が確かに簡単ですが、pozsが複数のキーを削除するために書いた関数はまだ便利です。たとえば、削除するキーがテーブルに保存されている場合、関数を使用してそれらをすべて削除できます。 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));
SELECT '{"a": "b"}'::jsonb - 'a';
9.5.2で動作します。しかしながら、 SELECT '{"a": "b"}'::jsonb #- '{a}';
うまくいきました!
これを行うもう1つの便利な方法は、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;
これについては ブログ で詳しく説明しています。