コーソル DatabaseエンジニアのBlog へようこそ

コーソル DatabaseエンジニアのBlogでは、 コーソル所属のDatabaseエンジニアである 渡部と守田がOracle Databaseを中心としたDatabaseに関わる技術情報を発信しています。

コーソルでは、Oracle Databaseをはじめとするデータベース全般に関わるサービス(コンサルティング、設計、構築など)、オラクル製品のプロダクトサポートサービスを提供しています。 また、不定期で無償の技術セミナーを開催しています。


コーソルでは、Oracle Databaseスペシャリストになりたいエンジニア、 Oracle Database技術を活かして働きたいエンジニアを絶賛募集中です。

hiring.png

コーソルについて知るためには・・・

エンジニアのスキル向上を支援する各種施策については・・・

コーソルのエンジニアの多くが従事する、「Oracle Database サポートエンジニアの仕事」の利点について知るためには・・・。

コーソルで働くことに興味を持たれた方は・・・

2018年5月17日

Oracle Cloud Infrastructure アイコン集

守田です。

オラクルエンジニア通信にて、クラウドのシステム環境図に利用できるアイコン素材集が公開されています。

オラクルエンジニア通信 アイコン集: Oracle Cloud Infrastructure
https://blogs.oracle.com/oracle4engineer/column_oci_graphics
cloud.JPG

私も過去Oracle Cloudの技術資料を作成したことがありましたが、
アイコンはお手製のものでした。公開されたアイコンを使用することで、一目で
Oracle Cloud のコンポーネントであると理解することができ、便利になりますね。

色は3色あるそうです。
cloud_icon.JPG

2018年5月 1日

4年目のJPOUG Oracle Database入学式やりますよ

渡部です。

JPOUGでは、Oracle Database入学式を2018年度も開催します :-)

  • タイトル : Introduction of Oracle Database Architecture
  • 2018-05-22(火)19:00 - 21:00
  • 株式会社コーソル セミナールーム 東京都千代田区麹町3-7-4 秩父屋ビル 7階
  • 参加費: 無料

内容

  • Oracle Databaseを学ぶ理由
  • OracleアーキテクチャとSQL処理
  • データとファイルI/O
  • テーブル、索引と実行計画
  • オプティマイザ統計
  • データベースバッファキャッシュ
  • SQLの解析と共有プール
  • ソートとPGA、一時表領域

お申し込みは以下のURLから!

Oracle Database入学式の開催は、2015年度、2016年度、2017年度に引き続き4回目になります。 毎年恒例のイベントになってきています。

2018年4月 4日

Oracle Autonomous Data Warehouse Cloud リリース

コーソル DatabaseエンジニアのBlogに新しい執筆者が加わりました! :-) これからは渡部+守田の2名体制でOracle Database周辺の技術についてお伝えしてゆきたいと思います。 どうぞよろしくお願いいたします。


守田です。私もこのBlogでOracle Database周辺技術をお伝えさせていただくことになりました。
新しもの好きで、なんでも1番乗りを目指す性格ですので、新しい技術情報を積極的に展開できたら、と考えております。
今後ともどうぞよろしくお願いいたします。

さて、さっそくですが、昨年の Oracle Open World で話題となった、「自動運用型のデータベース」が ついに Oracle Cloud でリリースされたそうです。 ADW.JPG マニュアルもすでに公開されていました(英語)。 ADWmanual.JPG US Oracle より発表されたプレスリリースによると、

『データベース・システムにおける管理とセキュリティの主要プロセスを自動化する自動稼働、自動保護、自動修復の機能を搭載しており、
パッチ適用、チューニング、アップグレードといったすべての処理が、重要なインフラストラクチャの稼動を中断することなく行われます』
とのことで、データベース管理の大半が自動化されるようです。

マニュアルをみたところ、「自動化されるので、そもそも触れない」状況となっており、 以下のようなコマンドが使用できない、または使用に制限があるようです。 ※一部抜粋

  • データベース管理に使用されるSQL
  • RMAN(Recovery Manager)
  • 表領域の追加や削除、変更
  • 索引、データベースリンク、マテリアライズド・ビューの作成、変更、削除
  • 初期化パラメータ
  • Oracle Real Application Testing や Oracle Database Vault などのオプション機能

などなど。
思ったより制限事項が多くて驚きました。

逆に考えると、「もうそんなことは考える必要はないよ!」ということなんでしょうね。

2017年12月16日

Oracle Cloud Infrastructureの仮想化基盤はKVM!

言いたいことはタイトルですべて集約されているのですが・・・ 一応画面キャプチャを。

oci_kvm.png

さらに一応蛇足気味な説明とつぶやきを・・・

Oracle Cloud Infrastructureは、従来でオンプレミス環境でしか実行できなかった 大規模ワークロードを実行できる、いわゆる「次世代」の(パブリック)クラウドインフラ基盤です。

画面キャプチャの通り、Oracle Cloud Infrastructureの仮想化基盤はKVMのようです。

これまで、ORACLEが主に使用していた仮想化基盤はXenでした。 具体的にはOracle Cloud Infrastructure Classic(旧Oracle Public Cloud)や、Oracle VMではXenを使用していました。

しかし、Red Hat Linuxをはじめとする主要なLinuxシステムでは、仮想化基盤をXenからKVMに移行しています。 また、XenのビッグユーザーだったAWSも、最近発表したインスタンスタイプでは仮想化基盤にKVMを使用しており、 おそらく今後はXenからKVMに移行することが予想されます。

このような流れがあり、ORACLEがXenを使い続けるのか、どのタイミングでKVMに移行するのかを 若干心配していましたが・・・ Oracle Cloud Infrastructureでは仮想化基盤にKVMを使用していることに遅まきながら気づき、安心した次第です。 (英語圏をふくめ、Oracle Cloud InfrastructureのKVM使用について触れている人が少ないような・・・)

JMESPATH TutorialをなぞってOracle Database 12c JSON機能を使ってみた

この記事は JPOUG Advent Calendar 2017 の16日目のエントリです。

前からすこし気になっていたOracle Database 12c JSON機能を使ってみました。

使うに当たっての手頃なターゲットとして、JMESPATH式のチュートリアルの内容を「なぞる」ことにします。 (ただし、Functionsは割愛・・・)

なお、JMESPATH式は、AWS CLIなどで使用されているJSONパス式です。

Basic Expressions - JMESPath Tutorial

JSONオブジェクトのキーを指定

キー名"a"を指定して、JSONオブジェクトからキーに対応する値を取得します。

{
  "a" : "foo", ←★★
  "b" : "bar",
  "c" : "baz"
}

JSONオブジェクトはあらかじめテーブルjson_dataのdata列に格納しておきます。

まず、テーブルjson_dataを作成します。(データ登録および更新をUPDATE文で統一したいため、1行ダミーのデータを入れています)

SQL> DROP TABLE json_data;

Table dropped.

SQL> CREATE TABLE json_data (
  2    data     CLOB CHECK (data IS JSON (STRICT))
  3  );

Table created.

SQL> INSERT INTO json_data (data) VALUES('{}');

1 row created.

data列にIS JSON制約を設定していることに注意してください。この制約がないと、ドット表記法が使えません。

列にはis jsonチェック制約が設定されている必要があり、これにより、整形式のJSONデータが含まれるようにします。これらの規則のどちらも順守されない場合、問合せのコンパイル時にエラーが発生します。

次にデータを登録します。

SQL> UPDATE json_data SET data ='
  2  {"a": "foo", "b": "bar", "c": "baz"}
  3  ';

1 row updated.

Oracle Database JSONに用意されているドット表記法アクセスでアクセスします。

.

SQL> SELECT j.data.a FROM json_data j;

A
--------------------------------------------------------------------------------
foo

別の方法として、JSON_xxxxファンクションを使う方法があります。

  • JSON_VALUE()はJSON_xxxxファンクションの1つで、取得する値がスカラー値の場合使用できます。
    • これ以外に、JSONフラグメントを返すJSON_QUERY()、表形式データを返す JSON_TABLE()があります
  • JSON_VALUE()の引数として、第1引数にJSONデータ、第2引数にOracle Databaseパス式を指定します。ドル記号'$'は問合せ先のJSONデータを示します。

.

SQL> SELECT JSON_VALUE(j.data, '$.a') FROM json_data j;

JSON_VALUE(J.DATA,'$.A')
--------------------------------------------------------------------------------
foo
  • JSON_VALUE()はドット表記法アクセス相当の処理を実行できますが、ご覧の通り、ドット表記法アクセスの方がシンプルで見やすいです。

キー名を連ねる形で指定

"a.b.c.d"のように、キー名を連ねる形で指定して、入れ子になっているJSONオブジェクトから値を取得します。

{
  "a" :
  {
    "b" :
    {
      "c" :
      {
        "d" : "value"←★
      }
    }
  }
  │
  │a.b.c.d
  ↓
"value"

JSONオブジェクトはあらかじめテーブルjson_dataの列dataに格納しておきます。

SQL> UPDATE json_data SET data ='
  2  {"a": {"b": {"c": {"d": "value"}}}}
  3  ';

1 row updated.

ドット表記法アクセスを用いて、入れ子になっているJSONオブジェクト( a → b → c → d)から値を取得できます。

SQL> SELECT j.data.a.b.c.d FROM json_data j;

A
--------------------------------------------------------------------------------
value

さっきの例と同様にJSON_VALUE()ファンクションを使った例も示します。

  • パス式の先頭にドル記号'$'がつく点をなどが異なりますが、基本的にドット表記法アクセスに類似しています。

.

SQL> SELECT JSON_VALUE(j.data, '$.a.b.c.d') FROM json_data j;

JSON_VALUE(J.DATA,'$.A.B.C.D')
--------------------------------------------------------------------------------
value

配列の要素

配列オブジェクトから2番目の値を取得します。

  • 配列の要素はインデックス値0からカウントするので、2番目の値に対応するインデックス値は1になります。

.

[
  "a",
  "b",←★
  "c",
  "d",
  "e",
  "f"
]
  │
  │[1]
  ↓
"b"

データを準備します。

SQL> UPDATE json_data SET data ='["a", "b", "c", "d", "e", "f"]';

1 row updated.

残念ながら、ドット表記では、トップレベルが配列であるJSONから、要素を得ることはできないようです。(この動作はどうなのだろうか・・・)

SQL> SELECT j.data[1] FROM json_data j;
SELECT j.data[1] FROM json_data j
             *
ERROR at line 1:
ORA-00923: FROM keyword not found where expected

JSON_VALUEを使えば、トップレベルが配列であるJSONから要素の値を取得できます。

SQL> SELECT JSON_VALUE(data,'$[1]') FROM json_data j;

JSON_VALUE(DATA,'$[1]')
--------------------------------------------------------------------------------
b

トップレベルが配列だと、ドット表記法でうまくアクセスできない制限があるようなので、トップレベルをオブジェクトにして、もう一度試すことにします。

{
  "k" :
  [
    "a",←★
    "b",
    "c",
    "d",
    "e",
    "f"
  ]
}

データを準備します。

SQL> UPDATE json_data SET data ='{"k": ["a", "b", "c", "d", "e", "f"]}';

1 row updated.

トップレベルが配列でなければ、ドット表記でも配列の要素を得ることができます。

SQL> SELECT j.data.k[1] FROM json_data j;

K
--------------------------------------------------------------------------------
b

なお、ここで説明したドット表記法における配列アクセスはOracle Database 12.2から使用可能です。 Oracle Database 12.1では使用できません。

単純なドット表記法構文を使用して、配列とその要素にアクセスできるようになりました。

キーおよび配列の要素の指定を組み合わせたパターン

つぎに、キーおよび配列の要素の指定を組み合わせたJSONオブジェクトから値を取得してみます。

{"a": {
  "b": {
    "c": [
      {"d": [0, [1, 2]]},
      {"d": [3, 4]}
    ]
  }
}}
    │
    │a.b.c[0].d[1][0]
    ↓
1

データを準備します。

SQL> UPDATE json_data SET data ='{"a": {
  2    "b": {
  3      "c": [
  4        {"d": [0, [1, 2]]},
  5        {"d": [3, 4]}
  6      ]
  7    }
  8  }}';

1 row updated.

ドット表記法でアクセスできます。

SQL> SELECT j.data.a.b.c[0].d[1][0] FROM json_data j;

A
--------------------------------------------------------------------------------
1

JSON_VALUE()ファンクション+パス式でも当然アクセスできます。

SQL> SELECT JSON_VALUE(j.data,'$.a.b.c[0].d[1][0]') FROM json_data j;

JSON_VALUE(J.DATA,'$.A.B.C[0].D[1][0]')
--------------------------------------------------------------------------------
1

Slicing - JMESPath Tutorial

スライスは、配列のインデックス値の範囲を指定して、配列の一部を取得する操作です。

  • JMESPathパス式では、配列のインデックス値の範囲は、[0:4]のように指定します。

.

{
  "k" :
  [
    0,←★
    1,←★
    2,←★
    3,←★
    4,←★
    5,
    6,
    7,
    8,
    9
  ]
}
    │
    ↓[0:5]
[
  0,
  1,
  2,
  3,
  4
]

データを準備します。すでに確認したように、Oracle Database JSONのドット表記法ではトップレベルが配列であるJSONから要素を得ることはできないようなので、トップレベルをオブジェクトにし、その中に配列を入れています。

SQL> UPDATE json_data SET data ='{"k": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}';

1 row updated.

パス表記法: インデックス値の範囲指定は [0:4]ではなく [0 to 4]ですが、うまくスライスできています。

SQL> SELECT j.data.k[0 to 4] FROM json_data j;

K
--------------------------------------------------------------------------------
[0,1,2,3,4]

次にJSON_xxxファンクションを試しますが、返される値がスカラー値ではないため、JSON_VALUEは使えません。代わりにJSON_QUERYを使用します。

パス表記法のときと同様に、インデックス値の範囲指定は [0:4]ではなく [0 to 4]で指定します。 ただし、以下のようにJSON_QUERYの引数にデータとパス式のみを指定すると、値が得られません。

SQL> SELECT JSON_QUERY(j.data, '$.k[0 to 4]') FROM json_data j;

JSON_QUERY(J.DATA,'$.K[0TO4]')
--------------------------------------------------------------------------------

その理由は、 ERROR ON ERRORを指定するとわかります。

SQL> SELECT JSON_QUERY(j.data, '$.k[0 to 4]' ERROR ON ERROR) FROM json_data j;
SELECT JSON_QUERY(j.data, '$.k[0 to 4]' ERROR ON ERROR) FROM json_data j
                                                             *
ERROR at line 1:
ORA-40480: result cannot be returned without array wrapper

エラーメッセージの通り、返される値が複数の場合には、配列ラッパーを指定して、複数の値を配列に変換する必要があります。 JSON_QUERY()にWITH CONDITIONAL WRAPPERを指定して、配列ラッパーを適用すると、返される複数の値を配列化した値が得られます。

SQL> SELECT JSON_QUERY(j.data, '$.k[0 to 4]' WITH CONDITIONAL WRAPPER ERROR ON ERROR) FROM json_data j;

JSON_QUERY(J.DATA,'$.K[0TO4]'WITHCONDITIONALWRAPPERERRORONERROR)
--------------------------------------------------------------------------------
[0,1,2,3,4]

別のパターンのスライス

開始インデックス値、終了インデックス値を変えたパターンですが、パス表記法、JSON_QUERY+パス式の両方で処理できます。

SQL> SELECT j.data.k[5 to 9] FROM json_data j;

K
--------------------------------------------------------------------------------
[5,6,7,8,9]

SQL> SELECT JSON_QUERY(j.data, '$.k[5 to 9]' WITH CONDITIONAL WRAPPER ERROR ON ERROR) FROM json_data j;

JSON_QUERY(J.DATA,'$.K[5TO9]'WITHCONDITIONALWRAPPERERRORONERROR)
--------------------------------------------------------------------------------
[5,6,7,8,9]

開始インデックス値を省略したスライス

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    │
    │[:5]
    ↓
[0, 1, 2, 3, 4]

Oracle Database JSONでは、スライスで開始インデックス値を省略できません。

SQL> SELECT j.data.k[  to 4] FROM json_data j;
SELECT j.data.k[  to 4] FROM json_data j
                  *
ERROR at line 1:
ORA-00900: invalid SQL statement

開始インデックス値は明示的に指定する必要があるようです。先頭のインデックス値として、0を指定すれば、想定した値が得られます。

SQL> SELECT j.data.k[0 to 4] FROM json_data j;

K
--------------------------------------------------------------------------------
[0,1,2,3,4]

SQL> SELECT JSON_QUERY(j.data, '$.k[0 to 4]' WITH CONDITIONAL WRAPPER) FROM json_data j;

JSON_QUERY(J.DATA,'$.K[0TO4]'WITHCONDITIONALWRAPPER)
--------------------------------------------------------------------------------
[0,1,2,3,4]

Projections - JMESPath Tutorial

JMESPATHのプロジェクションは、複数のデータ(コレクション)を内包するJSONを、「串刺し」するようにして配列データを得る操作です。

List and Slice Projections

List Projections

List Projectionsは、配列を対象にしたプロジェクションです。

{
  "people" :
  [
    {
      "first" : "James",←★
      "last" : "d"
    },
    {
      "first" : "Jacob",←★
      "last" : "e"
    },
    {
      "first" : "Jayden",←★
      "last" : "f"
    },
    {
      "missing" : "different"
    }
  ],
  "foo" :
  {
    "bar" : "baz"
  }
}
    │
    │people[*].first
    ↓
  [
    "James",
    "Jacob",
    "Jayden"
  ]

データを準備します。

SQL> UPDATE json_data SET data ='
  2  {
  3    "people": [
  4      {"first": "James", "last": "d"},
  5      {"first": "Jacob", "last": "e"},
  6      {"first": "Jayden", "last": "f"},
  7      {"missing": "different"}
  8    ],
  9    "foo": {"bar": "baz"}
 10  }
 11  ';

1 row updated.

ドット表記法ではList Projectionが可能です。

SQL> SELECT d.data.people[*].first FROM json_documents d;

PEOPLE
--------------------------------------------------------------------------------
["James","Jacob","Jayden"]

JSON_QUERY()ファンクション+パス式でもList Projectionが可能です。ただし、WITH CONDITIONAL WRAPPER の指定が必要です。

SQL> SELECT JSON_QUERY(j.data, '$.people[*].first'        WITH CONDITIONAL WRAPPER ERROR ON ERROR ) FROM json_data j;

JSON_QUERY(J.DATA,'$.PEOPLE[*].FIRST'WITHCONDITIONALWRAPPERERRORONERROR)
--------------------------------------------------------------------------------
["James","Jacob","Jayden"]

WITH CONDITIONAL WRAPPER を指定しないとエラーになります。

SQL> SELECT JSON_QUERY(j.data, '$.people[*].first'                              ERROR ON ERROR ) FROM json_data j;
SELECT JSON_QUERY(j.data, '$.people[*].first'                              ERROR ON ERROR ) FROM json_data j
                                                                                                 *
ERROR at line 1:
ORA-40480: result cannot be returned without array wrapper

Slice Projections

スライスプロジェクションは、配列を対象にし、スライスするプロジェクションです。 (JMESPath Tutorialの例が良くないので、スライスのインデックス値を変えています)

{
  "people" :
  [
    {
      "first" : "James",←★
      "last" : "d"
    },
    {
      "first" : "Jacob",←★
      "last" : "e"
    },
    {
      "first" : "Jayden",
      "last" : "f"
    },
    {
      "missing" : "different"
    }
  ],
  "foo" :
  {
    "bar" : "baz"
  }
}
  │
  │people[:2].first
  ↓
[
  "James",
  "Jacob"
]

データを準備します。

SQL> UPDATE json_data SET data ='
  2  {
  3    "people": [
  4      {"first": "James", "last": "d"},
  5      {"first": "Jacob", "last": "e"},
  6      {"first": "Jayden", "last": "f"},
  7      {"missing": "different"}
  8    ],
  9    "foo": {"bar": "baz"}
 10  }
 11  ';

1 row updated.

ドット表記法でも処理可能です。配列範囲の終了インデックス値が-1となることに気をつけてください。

SQL> SELECT j.data.people[0 to 1].first FROM json_data j;

PEOPLE
--------------------------------------------------------------------------------
["James","Jacob"]

JSON_QUERYファンクション+パス式でも同様に処理可能です。

SQL> SELECT JSON_QUERY(j.data, '$.people[0 to 1].first' WITH CONDITIONAL WRAPPER ERROR ON ERROR)  FROM json_data j;

JSON_QUERY(J.DATA,'$.PEOPLE[0TO1].FIRST'WITHCONDITIONALWRAPPERERRORONERROR)
--------------------------------------------------------------------------------
["James","Jacob"]

なお、ドット表記法において、返される要素数が1つになるようにインデックス値を変えると、返されるデータの型が配列ではなくなります。

SQL> SELECT j.data.people[0 to 0].first FROM json_data j;

PEOPLE
--------------------------------------------------------------------------------
James

SQL> SELECT j.data.people[0].first FROM json_data j;

PEOPLE
--------------------------------------------------------------------------------
James

返される要素数に応じて、返される型が変わるのはドット表記法独特の動作です。詳細は以下を参照してください。

なお、WITH CONDITIONAL WRAPPERを指定したJSON_QUERYでは、返される要素数が1でも配列として返されます。

SQL> SELECT JSON_QUERY(j.data, '$.people[0 to 0].first' WITH CONDITIONAL WRAPPER ERROR ON ERROR)  FROM json_data j;

JSON_QUERY(J.DATA,'$.PEOPLE[0TO0].FIRST'WITHCONDITIONALWRAPPERERRORONERROR)
--------------------------------------------------------------------------------
["James"]

SQL> SELECT JSON_QUERY(j.data, '$.people[0].first' WITH CONDITIONAL WRAPPER ERROR ON ERROR)  FROM json_data j;

JSON_QUERY(J.DATA,'$.PEOPLE[0].FIRST'WITHCONDITIONALWRAPPERERRORONERROR)
--------------------------------------------------------------------------------
["James"]

Object Projections

Object Projectionsは、オブジェクトを対象にするプロジェクションです。

{
  "ops" :
  {
    "functionA" :
    {
      "numArgs" : 2←★
    },
    "functionB" :
    {
      "numArgs" : 3←★
    },
    "functionC" :
    {
      "variadic" : true
    }
  }
}
  │
  │ops.*.numArgs
  ↓

[
  2,
  3
]

データを準備します。

SQL> UPDATE json_data SET data ='
  2  {
  3    "ops": {
  4      "functionA": {"numArgs": 2},
  5      "functionB": {"numArgs": 3},
  6      "functionC": {"variadic": true}
  7    }
  8  }
  9  ';

1 row updated.

ドット表記法では、キー箇所に'*'を指定できないため、Object Projectionができません。

SQL> SELECT j.data.ops.*.numArgs FROM json_data j;
SELECT j.data.ops.*.numArgs FROM json_data j
                  *
ERROR at line 1:
ORA-01747: invalid user.table.column, table.column, or column specification

JSON_QUERYファンクション+パス式では、キー箇所に'*'を指定でき、Object Projectionを実行できます。

SQL> SELECT JSON_QUERY(j.data, '$.ops.*.numArgs' WITH CONDITIONAL WRAPPER ) FROM json_data j;

JSON_QUERY(J.DATA,'$.OPS.*.NUMARGS'WITHCONDITIONALWRAPPER)
--------------------------------------------------------------------------------
[2,3]

Flatten Projections - JMESPath Tutorial

フラット化プロジェクションは、プロジェクション結果が配列の入れ子になっている場合、それをフラットにするプロジェクションです。

Oracle Database JSONでは相当する機能が無いようです。

Pipe Expressions - JMESPath Tutorial

パイプ相当の処理は、複数回JSON_xxxファンクションを適用することで一応実現できます(読みづらいですが)。

SQL> SELECT JSON_VALUE(JSON_QUERY(j.data, '$.people[*].first'     WITH CONDITIONAL WRAPPER ERROR ON ERROR ), '$[0]' ERROR ON ERROR ) FROM json_data j;

JSON_VALUE(JSON_QUERY(J.DATA,'$.PEOPLE[*].FIRST'WITHCONDITIONALWRAPPERERRORONERR
--------------------------------------------------------------------------------
James

MultiSelect - JMESPath Tutorial

JMESPATHのマルチセレクトは、JSON結果から、配列やオブジェクトを生成する処理です。

{
  "people": [
    {
      "name": "a",
      "state": {"name": "up"}
    },
    {
      "name": "b",
      "state": {"name": "down"}
    },
    {
      "name": "c",
      "state": {"name": "up"}
    }
  ]
}

を入力にして、people[].[name, state.name] というパス式を指定することで、以下のように配列の配列が得られます。

  │  people[].[name, state.name] 
  ↓
[
  [ "a", "up"   ],
  [ "b", "down" ],
  [ "c", "up"   ]
]

また、people[].{Name: name, State: state.name} というパス式を指定することで、以下のようにオブジェクトの配列が得られます。

  │  people[].{Name: name, State: state.name}
  ↓
[
  { "Name": "a",  "State": "up"   },
  { "Name": "b",  "State": "down" },
  { "Name": "c",  "State": "up"   }
]

このようにJMESPATHのマルチセレクトは、JSONの構造(形式)を変換するときに有用です。 また、変換における配列生成、オブジェクト生成の処理をパス式に組み込む形で記述できるため、非常にスマートに指定できます。

なお、Oracle Database JSONでは、JSONデータの生成はファンクションとして提供されており、パス式に組み込むことができないため、 JMESPATHのマルチセレクト類似の処理は実現できません。

ただ、そもそも、Oracle Databaseにおいて、JSON→JSONの変換処理を実現する必要性が高いかというと、微妙な気がします。(言い訳気味ですが)

むしろ、JSON→表の変換処理の方がありそうな気がしませんか?(強引)

というわけで、JSON_TABLEファンクションの紹介を兼ねて、JSON→表の変換処理を行ってみたいと思います。

JSON_TABLEファンクションを用いたJSON→表の変換

データを準備します。

SQL> UPDATE json_data SET data ='
  2  {
  3    "people": [
  4      {
  5        "name": "a",
  6        "state": {"name": "up"}
  7      },
  8      {
  9        "name": "b",
 10        "state": {"name": "down"}
 11      },
 12      {
 13        "name": "c",
 14        "state": {"name": "up"}
 15      }
 16    ]
 17  }
 18  ';

1 row updated.

JSON_TABLEファンクションを使い、表形式でデータを得ます。

JSON_TABLEファンクション内のCOLUMNS句で、得られる表の列について、データ型やパス式を指定しています。

SQL> SELECT x.* FROM json_data j, JSON_TABLE(j.data, '$.people[*]' ERROR ON ERROR
  2            COLUMNS (
  3              name  VARCHAR2(32) PATH '$.name',
  4              state VARCHAR2(32) PATH '$.state.name')) x;

NAME                             STATE
-------------------------------- --------------------------------
a                                up
b                                down
c                                up

それぞれのデータについて型の指定ができるため、ひらたく言うと「お行儀がイイ感じ」で表形式のデータを得られます。 JSON形式で得たデータを、表形式でデータベースで永続する場合に重宝しそうです。

Oracle Database JSON Tips

本文で記載した内容と一部重複しますが、最後にOracle Database JSONのTipsをまとめておきます。

JSON_xxxファンクションを試すときは ERROR ON ERRORを指定したほうが良い

  • ERROR ON ERRORを指定しないと、パス式がうまくマッチしなくてもNULLを返すだけで、Oracle Databaseは何も教えてくれません。

.

SQL> SELECT JSON_QUERY(j.data, '$.k[0 to 4]') FROM json_data j;

JSON_QUERY(J.DATA,'$.K[0TO4]')
--------------------------------------------------------------------------------
  • ERROR ON ERRORを指定すると、原因の特定に有用な情報を出力してくれます。

.

SQL> SELECT JSON_QUERY(j.data, '$.k[0 to 4]' ERROR ON ERROR) FROM json_data j;
SELECT JSON_QUERY(j.data, '$.k[0 to 4]' ERROR ON ERROR) FROM json_data j
                                                             *
ERROR at line 1:
ORA-40480: result cannot be returned without array wrapper

ドット表記法を使う場合はJSONとして参照する列にIS JSON制約を設定する必要がある

設定しないと、ORA-00904が発生します。エラーメッセージがあまり親切でないので要注意です!

SQL> SELECT j.data1.a FROM json_data2 j;
SELECT j.data1.a FROM json_data2 j
       *
ERROR at line 1:
ORA-00904: "J"."DATA1"."A": invalid identifier

.

JSON_xxxファンクションでは、返される値の種類に応じてファンクションを使い分ける必要がある。

Oracle Database JSONでは、返される値の種類に応じてファンクションを使い分ける必要があります。 具体的には以下のとおりです。

  返される値                  JSON_xxxファンクション
  --------------------------- ------------
  スカラー値                  JSON_VALUE
  JSON(配列、オブジェクト)   JSON_QUERY

JSON_QUERYが複数の値を返す場合、配列にラップする必要がある。

List Projectionの説明の箇所で取り上げた実行例ですが、JSON_QUERYが複数の値を返す場合、配列にラップしないと、エラーORA-40480が発生します。

SQL> SELECT JSON_QUERY(j.data, '$.people[*].first'                              ERROR ON ERROR ) FROM json_data j;
SELECT JSON_QUERY(j.data, '$.people[*].first'                              ERROR ON ERROR ) FROM json_data j
                                                                                                 *
ERROR at line 1:
ORA-40480: result cannot be returned without array wrapper

WITH CONDITIONAL WRAPPER などを指定すれば、複数の値をラップした配列が返されます。

SQL> SELECT JSON_QUERY(j.data, '$.people[*].first'        WITH CONDITIONAL WRAPPER ERROR ON ERROR ) FROM json_data j;

JSON_QUERY(J.DATA,'$.PEOPLE[*].FIRST'WITHCONDITIONALWRAPPERERRORONERROR)
--------------------------------------------------------------------------------
["James","Jacob","Jayden"]

JSON_QUERYで、パス式の評価結果がスカラー値になる場合があるならWITH CONDITIONAL WRAPPERを指定する

JSON_QUERYファンクションはスカラー値を返せません。パス式の評価結果が常にスカラー値になるとわかっているのなら、JSON_VALUEを使えばよいのですが、 対象のJSONドキュメントに応じて、評価結果がJSON(の一部)になったり、スカラー値になったりする場合はどうすればよいのでしょうか?

WITH CONDITIONAL WRAPPERを指定しておくと、評価結果がスカラー値になった場合にみ配列でラップしてくれます。なかなか気が利いています。

WITH CONDITIONAL WRAPPERがデフォルトの動作でもよい気がしますが、なにか理由があるのでしょうかねぇ・・・?

2017年12月 9日

DB Online記事 Oracle Database Standard Editionユーザーが次に選ぶべきDBはどれだ?!

先日、DB Online記事 Oracle Database Standard Editionユーザーが次に選ぶべきDBはどれだ?! に御協力させていただきました。 記事は以下に通りです。

Oracle Database 12cのバージョン12.1.0.2のリリースを受けて、2016年1月末、小規模ユーザー向けライセンスとして広く提供されてきたStandard Edition(以下、SE)およびStandard Edition One(以下、SE1)は、新たにOracle Standard Edition 2(以下、SE2)に一本化された。この結果、Standard Editionの新規ユーザーは必然的にSE2を導入することになったが、既存のSEやSE1のユーザーは、どのようなアップグレードを選択しており、また今後選択すべきなのか。エンタープライズ データベースのエキスパートにお集まりいただき、考えなどを聞いてみた。

個人的にあまり経験がない活動で、取材までは若干緊張しましたが、 ご一緒させていただいた方々が、昔からお世話になっている、アシストの岸和田さま、日本オラクルの桑内さま、 そして、ラグビー観戦という共通の話題があった谷川さまということで、 リラックスして取材対応を終えることができました。ご一緒させていただいた皆さま、ありがとうございました!

内容が、記事をご覧になった方のお役に立てば幸いです。

#いつも思うのですが、「あんな」とりとめのない内容を、きっちり記事にまとめるライターさんって、ほんとうに凄いなと

2017年12月 6日

Oracle CloudWorld Tokyo 2017の座談会に参加させていただきました

本日、Oracle CloudWorld Tokyo 2017の座談会に参加させていただきました。

技術者によるクラウド座談会 ネットワーク、運用管理などクラウド構築で押さえるべきポイントを語る セキュリティ、運用管理、セキュアなネットワークの構築、オンプレミスからの移行方法など、クラウドを導入する際には技術的に押さえておくべきポイントがあります。今回は、パブリック・クラウドの構築経験のある優秀な技術者を招いて、実際の構築経験から学んだ失敗しないための心構えやクラウド構築の秘訣、さらに最新技術のトレンドをお聞きします。

現状、弊社のビジネスの大多数は、オンプレミスでOracle Databaseをご利用いただくお客様に対する 技術サービス提供ですが、クラウドの案件、特にオンプレミスからクラウドへ移行するご依頼も多数いただいております。 そのなかで得た知見の一部を共有させていただきました。

短い時間ではありましたが、ご参考になれば幸いです。 :-)

なお、同一の内容を、Oracle CloudWord Osakaでもお話させていただく予定です。

#Tokyoはうまい具合に時間ぴったりで終われたけど、Osakaはこんなにうまくいくんだろうか・・・

2017年11月28日

ORACLE MASTER Platinum取得者数 No.1 V2達成!でパーティやったよ

コーソルは、昨年からORACLE MASTER Platinumの取得者数でNo.1の座を維持し続けていますが、 これを祝ってパーティを開催しました :-)

パーティで使ったスライドから1枚抜粋。徐々に合格者数を伸ばしてきたことがわかりますね。:-)

20171124_Platinum_No1_Party_graph.png

このくす玉は、まだ取得者No.1ではないときに、No.1を記念してママさんエンジニアが産休中に手作りしてくれたもの。

20171124_platinum_no1_party.jpg

来年もNo.1になってV3を達成し、またこのくす玉と一緒にお祝いをしたいと思います!

補足

コーソルでは、エンジニアのスキルアップを重視する会社であり、それを十二分に踏まえて、人事制度や資格取得支援制度がつくられています。

エンジニアのスキルアップの一環として、ORACLE MASTER Platinumの取得を目指す取り組みは、 日本オラクル Oracle University様に事例としてご紹介いただいています。

ou_platinum.png

2017年10月17日

11/17(金)に #Docker しばりの #JPOUG in 15 minutes やりますよ

in15m6-1024x576.png

以前から注目されている基盤技術であるDockerの基礎から応用まで、オラクル製品に絡めた形で理解できるイベントを企画しました。 Dockerに興味がある方、Dockerについて一通り理解しておきたい方にお勧めです!

  • 日時 : 2017年11月17日(金)19:00~21:30(開場および受付開始: 18時30分)
  • 場所 : 東京都港区北青山2-5-8 オラクル青山センター 13階セミナールーム

2017年10月17日時点のセッションタイトルを以下に記載します。基礎から応用まで幅広く理解できる構成になっています。 企画サイドの立場で手前味噌ですが、非常に魅力的な構成になっていると思いますよ :-)

  • はじめてのDockerパーフェクトガイド(2017年版) : 日本オラクル 早川 博さん
  • Oracle Database (CDB) on Docker を動かしてみる : 日本オラクル 佐々木 亨さん
  • Oracle Linux と Docker とその周辺のもの : 渡辺 剛さん (vExpert!)
  • Oracle RAC on Docker : 大島正樹さん 株式会社日立システムズ 
  • Oracle対応アプリケーションのDockernize事始め : 永安悟史さん アップタイム・テクノロジーズ
  • DBエンジニアのマイクロサービス入門 ~Oracle Database と Docker ではじめる API サービス~ : 吉田成利さん NTTデータ先端技術

11/17(金)はぜひOACまで是非お越しくださいませー

Oracle OpenWorld 2017 Tweetsまとめました

今年コーソルからOracle OpenWorld 2017に参加した2名のメンバーが無事に帰国しました。

例年と同じく、彼らが現地でつぶやいたTweetをtogetterにまとめました。「Oracle OpenWorldに現地参加することの楽しさ」が伝われば嬉しいです!

ちなみに、過去OOWに参加したときのTweetまとめはこちらです。

投稿内容は個人の意見であり、所属企業・部門見解を代表するものではありません。

プロフィール

Ryota WATABE / 渡部 亮太

100x100.jpg

  • Oracle ACE
  • AWS Certified Solutions Architect - Associate
  • ORACLE MASTER Platinum Oracle Database 11g, 12c 他多数

Norio Morita / 守田 典男

Norio Morita

  • 新しもの好きな Oracle Fighter。
  • 保有資格 : ORACLE MASTER Platinum Oracle Database 11g, 12c 他多数