#OracleのNUMBERとDb2のNUMBER
前回投稿の
[・Db2のOracle互換機能を使ってみた😃<7> ~NUMBERタイプの互換性(1)~][7]
では、「NUMBERデータ・タイプの互換性」によって、Db2でもNUMBERというデータ・タイプの指定ができるようになりますが、それは内部的には同等のDECIMAL型、またはDECFLOAT(16)にマッピングされることであるということをご紹介しました。
しかしOracleのNUMBERとDb2のDECIMALやDECFLOATは、異なる点がいろいろあります。
そのためOracleのNUMBERとDb2のNUMBERにも、その違いが影響してきてしまうのです。
Db2ではそれぞれの数値の特性に合わせて、いろいろなタイプの数値型を用意していますが、OracleはほぼすべてをNUMBERという1つのタイプで扱うようにしているというDBMSの実装方針の違いによるため、仕様の違いが出てくるのは仕方かないことかなと個人的には思います。
では、OracleのNUMBERとDb2のNUMBERは、どのような違いがあるか。
大別すると、以下の3つになるかと思います。
1.小数点や0などの数字の表示上の違い
2.四捨五入など数値の丸めの違い
3.精度と位取りに指定できる値の違い
ということで、今回はまず上記の1に関連した、表示上の違い関してご紹介します。
#■OracleのNUMBERとDb2のNUMBERの異なる点
##その1:表示上の違い
###整数値の小数点
OracleとOracle互換のDb2では、同じNUMBER(p)の指定でも、表示結果の小数点の有無に違いがあります。
Oracle NUMBERは位取り指定があってもなくても、挿入値が整数であれば、表示結果に小数点がつきません。
一方、Db2のNUMBERはマッピングされたDECIMALの仕様に従うので、挿入値が整数の場合は小数点以下は0で埋められ、他の小数点以下がある値とも桁数が揃って表示されます。
また位取りの指定が0の場合は、小数点のみがついて小数点以下がない形式で表示されます。
具体的には以下のような結果の違いになります。
(注1:SQL* Plusではカラムの表示形式を設定すれば小数点を表示することもできますが、ここではそのような設定をしていないことを前提としています)
小数点の有無の違い
OracleのNUMBERの場合【図1】
Oracle互換Db2のNUMBERの場合【図2】
Oracleでは整数のみを格納する数値データ型というものが特にあるわけではないので、NUMBER(p)やNUMBER(p,0)を使うと思います。でもこの定義をそのままOracle 互換のDb2で使用した場合、INTEGERなどの整数型ではなく、DECIMAL(p.0)にマッピングされ、【図2】のDb2の結果のように小数点付きで表示さます。
このような違いがあるため、Oracle互換のDb2で、整数は小数点がつかないようにしたい場合は、NUMBERでなく明示的にSMALLINT, INTETER, BIGINTを使う検討をお勧めします。またこれらは2進整数であるので、DECIMALよりも処理効率が良いデータ・タイプです。
###先行0の有無
もう1つの表示上の違いは、先行0の有無です。
これは1以下の小数の話ですが、例えば0.5という数値の場合、Oracleの場合は .5 というように先行0は表示されませんが、Db2では0.5と先行の0も表示されます。
以下は【図1】のOracleのNUMBERの場合の例と同じ表のC2を0.5に更新してSELECTした結果です。
OracleのNUMBERは、先行0は表示されない【図3】
Db2で1以下の先行0を表示しないデータ・タイプというものはないので、この違いはいかしかたないのですが、もし文字型で受け取っても良いのであれば、以下のようにCHARにキャストするということで、0を除外することは可能です。
このCHAR型へのキャストは、先述の小数点の有無の違いへの対応としても使えます。
【図4】は、【図2】のDb2の表のC2を0.5に更新し、C1,C2そのままとCHAR(10)へのCAST結果をそれぞれSELECTした結果です。
Oracle互換NUMBERのCHAR型へのキャスト結果【図4】
OracleのNUMBERとDb2のNUMBERの異なる点として、今回は表示上の話をご紹介しました。
次回は2つ目の違いとして、四捨五入など数値の丸めについて触れたいと思います。
つづく
##関連投稿
[・Db2のOracle互換機能を使ってみた😃<1> ~データベースの作成~][1]
[1]:https://qiita.com/Seven_Marine/items/1a9009a29e78fc80a2f0
[・Db2のOracle互換機能を使ってみた😃<2> ~可変長列の末尾ブランクの違い~][2]
[2]:https://qiita.com/Seven_Marine/items/f7a31fc71a728282e043
[・Db2のOracle互換機能を使ってみた😃<3> ~空文字(長さ0の文字)の扱い(1)~][3]
[3]:https://qiita.com/Seven_Marine/items/470d58226fe89f017b2a
[・Db2のOracle互換機能を使ってみた😃<4> ~空文字(長さ0の文字)の扱い(2)~][4]
[4]:https://qiita.com/Seven_Marine/items/612e1ca67054337f9758
[・Db2のOracle互換機能を使ってみた😃<5> ~空文字(長さ0の文字)の扱い(3)~][5]
[5]:https://qiita.com/Seven_Marine/items/28c73c824619baf48354
[・Db2のOracle互換機能を使ってみた😃<6> ~空文字(長さ0の文字)の扱い(4)~][6]
[6]:https://qiita.com/Seven_Marine/items/5cc1afad26ea4eea4644
[・Db2のOracle互換機能を使ってみた😃<7> ~NUMBERタイプの互換性(1)~][7]
[7]:https://qiita.com/Seven_Marine/items/74bf4af0e65de2222e33
[・Db2のOracle互換機能を使ってみた😃<9> ~NUMBERタイプの互換性(3)~][9]
[9]:https://qiita.com/Seven_Marine/items/6a47ea5ea6418c6db6e2
[・Db2のOracle互換機能を使ってみた😃<10> ~NUMBERタイプの互換性(4)~][10]
[10]:https://qiita.com/Seven_Marine/items/b260192afc9ec5c60899
お断り:
当投稿は、Database migration to DB2-IBM Japan Community Wikiに掲載のブログを、Qiita用に書き直したものです。
本資料掲載事項は、ある特定の環境・使用状況においての正確性は確認されていますが、すべての環境において同様の結果が得られる保証はありません。
これらの技術を自身の環境に適用する際には、自己の責任において十分な検証と確認を実施いただくことをお奨めいたします。