5 SQL/JSON条件IS JSONおよびIS NOT JSON

SQL/JSON条件is jsonおよびis not jsonは補足的な条件です。これらは、引数が構文的に正しい(つまり、整形式の)JSONデータかどうかをテストします。オプションのキーワードVALIDATEによって、データが特定のJSONスキーマに関しても有効かどうかをテストします。

is jsonis not jsonは、CASE式またはSELECT文のWHERE句で使用できます。is jsonはチェック制約で使用できます。

テストしたデータが構文的に正しいときに、キーワードVALIDATEが存在しない場合、is jsonはtrueを返し、is not jsonはfalseを返します。

キーワードVALIDATEが存在する場合、データは指定されたJSONスキーマに関して正しい形式であり有効であること(またはIS NOT)を確認するためにテストされます。キーワードVALIDATE (オプションでキーワードUSINGが続く)の後には、検証対象のJSONスキーマであるSQL文字列リテラルが後続している必要があります。

解析中(または検証中)にエラーが検出された場合は、エラーが発生することはなく、データが整形式ではない(または不正)とみなされます。is jsonはfalseを返し、is not jsonはtrueを返します。(解析中または検証中以外にエラーが検出された場合は、そのエラーが発生します)。

整形式のデータとは、構文的に正しいデータであることを意味します。テキストとして格納されているJSONデータは、厳密な構文と緩慢な構文と呼ばれる2つの意味での整形式にすることができます。また、テキストのJSONデータの場合は、JSONオブジェクトに重複したフィールド(キー)を含めることができるかどうかを指定できます。

anyデータ型(テキストまたはJSON型)のJSONデータの場合:

  • 整形式のデータの文書に最上位レベルのスカラー値を含めることができるかどうかを指定できます(データベース初期化パラメータcompatible20以上の場合)。また、有効である必要があることも指定できます。

  • 特定のJSONスキーマに対して、データを検証する必要があること(またはIS NOT JSONによって、その必要がないこと)を指定できます。

テキストのJSONデータがデータベース内で生成される場合は、キーワードSTRICTを指定した条件is jsonを満たします。これには次の方法による生成が含まれます。

  • SQL/JSON生成関数を使用(FORMAT JSONまたはTREAT AS JSONにキーワードSTRICTを指定しない場合。このキーワードには、データがJSONデータであることを宣言する意味があり(ユーザーがそれを保証します)、整形式であるかどうかはチェックされません)

  • SQLファンクションjson_serializeの使用

  • PL/SQL DOMでのSQLファンクションto_clobto_blobまたはto_stringの使用

  • SQL/JSONファンクションjson_queryの使用

  • FORMAT JSONを指定したSQL/JSONファンクションjson_tableの使用

ノート:

JSON型のデータは一意のオブジェクト・キー(フィールド名)のみを持ち、厳密な構文と緩慢な構文の概念は適用されません。(任意のデータ型の) JSONデータをシリアライズしてテキストのJSONデータを生成する場合、結果の構文は常に厳密です。

JSONデータ型を使用してJSONデータを格納し、is jsonチェック制約を使用する場合、次のようになります。

  • キーワードDISALLOW SCALARSを指定した場合、JSON列には最上位レベルのスカラーJSON値を持つ文書を格納できません。

  • キーワードを指定しない場合、またはDISALLOW SCALARS以外のキーワードを指定した場合、is json制約は無視されます。それらのキーワードでは何も変更されません。

キーワードCHECKおよびIS JSONは省略できます。たとえば、次の2つのチェック制約は同等であり、どちらも、列jcolの値がJSON文字列であることを確認します:

CHECK (jcol IS JSON VALIDATE '{"type": "string"}')
jcol VALIDATE '{"type": "string"}'

関連項目:

5.1 JSONオブジェクトの一意フィールドと重複フィールド

JSON標準では、JSONオブジェクトに重複するフィールド名がないことが推奨されています。Oracle Databaseでは、エラーを発行することでJSON型のデータに対してこれが強制されます。テキスト形式で格納されている場合は、キーワードWITH UNIQUE KEYSを指定したis jsonチェック制約を使用して、重複するフィールド名を許可しないことをお薦めします。

テキスト(VARCHAR2CLOBBLOB列)で格納されている場合、重複する名前のチェックに時間がかかるため、デフォルトでは、JSONデータの重複するフィールド名が許可されています。テキストで格納されたJSONデータのこのデフォルトの動作によって一貫性のない動作になる可能性があるため、デフォルトには依存しないことをお薦めします。

このデフォルトの動作をオーバーライドして、フィールドが重複しているオブジェクトを含むデータを挿入しようとしたときにエラーが発生するようにできます。これを行うには、キーワードWITH UNIQUE KEYSを指定してis jsonチェック制約を使用します。(これらのキーワードは、JSON型の列に挿入されるデータには影響しません。)

整形式のテキストJSONデータで重複フィールド名が許可されるかどうかは、整形式かどうかの確認に、厳密な構文と緩慢な構文のどちらが使用されるかとかかわっています。

5.2 厳密なJSON構文と緩慢なJSON構文について

入力時には、JSONのOracleのデフォルト構文は緩慢です。この構文は、オブジェクト・フィールドに対してJavaScript構文を反映し、ブール型の値およびnull値では大/小文字が区別されず、数字、ホワイトスペースおよびUnicode文字のエスケープについてはより寛容です。Oracleは、標準に厳密に準拠したJSONデータを出力します

標準ECMA 404JSONデータ交換フォーマット、およびECMA 262ECMAScript言語仕様により、JSON構文が定義されます。

これらの仕様(ECMAScript第5.1版より前)によると、各JSONフィールドおよび各文字列値は、二重引用符(")で囲む必要があります。Oracleはこの厳格なJSON構文をサポートしており、常に出力時にこの構文を尊重しますが、これは入力データのデフォルトの構文ではありません

JavaScript表記法では、オブジェクト・リテラルで使用されるフィールドは、二重引用符で囲むことができますが、必須ではありません。これはまた、一重引用符(')で囲むこともできます。ECMA 262第5.1版では、このようなフィールドを許可するなど、いくつかの方法で厳密な構文が緩和されました。Oracleでは、ECMAScript 5.1で指定されたこの構文がサポートされています。

デフォルトでは、Oracleは入力データを受け入れるときに緩慢なJSON構文を使用します。この構文は、ECMAScript 5.1で指定されている構文とは細部が1つ異なります。Oracleでは、エスケープされていない行および段落区切り文字(U+2028およびU+2029)をJSON文字列に含めることができます。(これはJSON5の場合も同様で、この違いを除けば、ECMAScript 5.1の適切なサブセットです。)

さらに、実際には、一部のJavaScript実装(ただし、JavaScript標準ではありません)では次の1つ以上が可能です。

  • truefalseおよびnullの大/小文字の相違(TRUETrueTrUefALSeNulLなど)。

  • 配列の最後の要素またはオブジェクトの最後のメンバーの後ろに追加されるカンマ(,) ([a, b, c,]{a:b, c:d,}など)。

  • 先頭に1つ以上の0がある数字(0042.3など)。

  • 小数点の前に0がない小数(0.14ではなく.14など)。

  • 小数点の後に小数部分がない数字(342.1.e27など)。

  • 数値がマイナスではないことを意味する、数字の前のプラス記号(+) (+1.3など)。

この構文も、Oracleのデフォルトの(緩慢な) JSON構文の一部として入力時に許可されます。(厳密な数字構文は、JSON標準を参照してください。)

ASCIIのスペース文字(U+0020)以外にも、JSON標準では、引用符で囲まれたフィールドまたは文字列値の外側で使用される場合、次の文字は重要でないホワイトスペース(無視される)として定義されています。

  • タブ、水平タブ(HT ^I、10進数の9、U+0009、\t)

  • 行送り、改行(LF ^J、10進数の10、U+000A、\n)

  • キャリッジ・リターン(CR ^M、10進数の13、U+000D、\r)

ただし、Oracleの緩慢なJSON構文では、ASCII制御文字([Ctrl]+[0]から[Ctrl]+[31])のすべて、およびASCIIスペース文字(10進数の32、U+0020)は、重要でないホワイトスペース(引用符で囲まれたフィールドまたは文字列値の外部で無視されます)として処理されます。制御文字には次のようなものがあります。

  • Null (NUL ^@、10進数の0、U+0000、\0)

  • ベル(NEL ^G、10進数の7、U+0007、 \a)

  • 垂直タブ(VT ^K、10進数の11、U+000B)

  • エスケープ(ESC ^[、10進数の27、U+001B、\e)

  • 削除(DEL ^?、10進数の127、U+007F)

Oracleの厳密な構文(ECMAScript 5.1など)では、ASCIIスペース文字(10進数32、U+0020)以外のすべてのUnicodeホワイトスペースは重要でないものとして扱われます。また、厳密な構文では、U+0020は、引用符で囲まれたフィールドまたは文字列値内で許可され、エスケープされていない唯一のホワイトスペースです。

Oracleの緩慢なJSON構文では、引用符で囲まれていないオブジェクト・フィールドに、ホワイトスペースとJSON構造文字(左右の大カッコ([])と中カッコ({})、コロン(:)およびカンマ(,))を除く任意のUnicode文字を含めることができますが、エスケープ・シーケンスは許可されません。

厳密なJSON構文と緩慢なJSON構文の両方で、引用符で囲まれたオブジェクト・フィールドおよび文字列値に任意のUnicode文字を含めることができます。それぞれを含めるには、ASCIIエスケープ構文\uの後にUnicodeコード・ポイントを表す4つのASCII 16進数を続けます。

次のUnicode文字は、\uの後にコード・ポイントまたは特殊なエスケープ・シーケンスが続くフィールドおよび文字列で表される必要があります

  • ASCII制御文字のバックスペース(CONTROL-H)、フォームフィード(CONTROL-L)、改行(行送り)、キャリッジリターン(CONTROL-M)、および(水平)タブ(CONTROL-I)。

    \b (バックスペース)、\f (フォーム・フィード)、\n (改行)、\r (キャリッジリターン)および\t (タブ)を使用します。

  • 二重引用符(")、スラッシュ(/)およびバックスラッシュ(\)文字。

    これらをエスケープするには、それぞれの前にバックスラッシュ文字\"\/、および\\を付けます。

表5-1は、JSON構文のいくつかの例を示しています。

表5-1 JSONオブジェクト・フィールドの構文例

整形式かどうか

"part number": 1234

緩慢および厳密: はい。スペース文字は許可されます。

part number: 1234

緩慢(および厳密): いいえ。引用符で囲まれていない名前では、スペース文字を含むホワイトスペース文字は許可されません。

"part\tnumber": 1234

緩慢および厳密: はい。タブ文字のエスケープ・シーケンスは許可されます。

"part    number": 1234

緩慢: はい、厳密: いいえ。エスケープされていないタブ文字は、緩慢な構文でのみ使用できます。厳密な構文で許可されるエスケープされていないホワイトスペース文字は、スペース(U+0020)のみです。

"\"part\"number": 1234

緩慢および厳密: はい。名前が引用符で囲まれている場合、エスケープされている二重引用符は許可されます。

\"part\"number: 1234

緩慢および厳密: いいえ。二重引用符を埋め込むには、フィールド名を引用符で囲む必要があります。

'\"part\"number': 1234

緩慢: はい、厳密: いいえ。一重引用符で囲まれた名前(オブジェクト・フィールドと文字列)は、緩慢な構文でのみ許可されます。引用符で囲まれた名前では、エスケープされている二重引用符が許可されます。

"pärt : number":1234

緩慢および厳密: はい。引用符で囲まれた名前では、任意のUnicode文字が許可されます。これには、ホワイトスペース文字と、コロン(:)などの、JSONの構造的な文字が含まれます。

part:number:1234

緩慢(および厳密): いいえ。引用符で囲まれている名前では、構造文字は許可されません。

関連項目:

5.3 厳密なJSON構文と緩慢なJSON構文の指定

Oracle Database向けのデフォルトのJSON構文は緩慢です。構文が厳密か緩慢かが問題になるのは、SQL/JSON条件is jsonおよびis not jsonの場合のみです。他のすべてのSQL/JSONファンクションおよび条件では、入力を解析するために緩慢な構文が使用され、出力を戻すために厳密な構文が使用されます。

特定のテキストのJSONデータに厳密に正しい構文が使用されていることを確認する必要がある場合は、最初にis jsonまたはis not jsonを使用してチェックしてください。

JSON標準に応じてデータを厳密な整形式としてチェックするよう指定するには、(STRICT) (カッコを含む)をis jsonまたはis not json式に追加します。

例5-1に、これを示します。これは例4-2と同じですが、列に挿入されたすべてのデータがJSON標準に応じた整形式であることを確認するために(STRICT)が使用されています。

関連項目:

CREATE TABLEの詳細は、Oracle Database SQL言語リファレンスを参照してください。

例5-1 テキストのJSONデータが厳密な整形式であることを確認するためのチェック制約でのIS JSONの使用

JSON列はデータ型VARCHAR2です。この型はJSON型ではないため、is jsonチェック制約が必要となります。この例では、厳格な、つまり標準のJSON構文が指定されています。

CREATE TABLE j_purchaseorder
  (id          VARCHAR2 (32) NOT NULL PRIMARY KEY,
   date_loaded TIMESTAMP (6) WITH TIME ZONE,
   po_document VARCHAR2 (32767)
   CONSTRAINT ensure_json CHECK (po_document is json (STRICT)));