web-dev-qa-db-ja.com

PostgreSQL 9.3ですべてのJSONスカラーを検索できますか?

私たちはPostgres 9.3を使用しており、そのバージョンで新しくなったJSON列を利用しています。バージョン9.4では、JSONを処理するための多数のユーティリティ関数と、新しいJSONB列が追加されました。 http://www.postgresql.org/docs/9.4/static/functions-json.htmlhttp://www.postgresql.org/docsと比較すると、これを確認できます/9.3/static/functions-json.html

9.4には関数json_typeof JSONオブジェクトのタイプを返します(文字列: 'string'、 'number'、 'array'、 'object'など)。9.3ですべてを取得する実用的な方法があるかどうか知りたいスカラーである行(または、オブジェクトではない私たちにとっても同様に有用)。

特定のテーブルのcomment列を常にJSONオブジェクトにする必要があります。つまり、次のようなクエリを実行できます。

SELECT comment->>'author' as author_name
FROM our_table

一部の行のコメント列のJSONがオブジェクトであるが、そのようなキーがない場合、NULLを返すだけです。

ただし、テーブルにスカラーが1つでもある場合、クエリはエラーで失敗します

ERROR: cannot extract element from a scalar
SQL state: 22023

これは、主にエラーが原因で、この列に文字列が書き込まれることがあったため、問題です。クエリでこれらをフィルターで除外するか、一度に削除できるようにすべてを特定する合理的な方法はありますか?

3
jwg

そのままでは恐ろしいですが、オブジェクトから要素を抽出するためにattemptsというPL/PgSQL関数を記述し、失敗した場合は例外をトラップし、成功した場合はtrueを、例外の場合はfalseを返すことができます。

未テスト:

_create or replace function json_isobject(obj json)
returns boolean immutable language plpgsql as $$
begin
    begin
        perform obj->'';
    exception
      when invalid_parameter_value then
        return false;
      when others then
        raise;
    end;
    return true;
end;
$$;
_

これは、呼び出しごとにサブトランザクションを作成するため、かなり非効率的です。

または、9.4に更新することもできます。


9.4では、報告されたエラーを再現できません。 jsonスカラーでキーを検索しようとすると、nullが返されます。

_test=> select ('{"k":"v"}'::json) -> 'k' -> 'blah';
 ?column? 
----------

(1 row)
_

...スカラーを逆参照するために_->>_を使用する場合も同様です。

したがって、この関数が9.3で機能するかどうか、そして9.4ではできないかどうかわかりません。 9.4互換になるには、current_setting('pg_version_num') >= 90400かどうかをテストし、代わりに_json_typeof_に基づいて結果を返す必要があります。

報告されたエラーをトリガーするために使用するのと同じ式を使用するようにそれを適応させる必要があるかもしれません。

2
Craig Ringer

1つの方法は、JSON列の文字列形式を確認することです。オブジェクトは '{'で開始するか、多分スペースの後にその文字が続く必要があります。そう

SELECT *
FROM data_write
WHERE comment::text NOT SIMILAR TO ' *{%'

ほとんどの場合をキャッチする必要があります。ただし、JSONB列とは異なり、JSON列はJSONを正規の形式ではなく、元の形式で格納します。したがって、このメソッドは、たとえば、一致しない別のスペース文字で始まる奇妙なJSONが存在する可能性を排除しません。

0
jwg