本ページは広告が含まれています。気になる広告をクリック頂けますと、サーバ運営費になります(^^
Postgresで sum演算させると、返ってくる値はnumeric型です。これをC#の変数に格納したい時、C#の変数は何型にすべきなのでしょうか。
C#の数値型
色々と種類があります。私は長年、あいまいに利用してきていますが、とりあえず整数ならint、少数ならfloat、お金を扱うならdecimalといった何となく、定石で決めていて、なぜそれで設計するのかという事がなく、postgresでnumericが返ってきた時にc#側の変数に格納したい時はどの変数で受けるのが最適なんだろうと疑問に思った所です。
整数 (int や ushort など)
2 進表現の浮動小数点実数 (float,double)
10 進表現の浮動小数点実数 (decimal)
intは、System.Int32の別名
これも長年疑問でした。大文字で始まる変数と、小文字で始まる変数。どっちを使っても特にエラーが出るわけでもなく。んじゃ、どっちを使うのが最適なの?という疑問です。
intは、System.Int32の別名「エイリアス」になります。つまり動作は同じです。同じものなのです。なんで大文字で書く時と、小文字の時とあるのかなとずっと疑問でしたが、同じもんだ!と思えばいいですね。なんでこれが必要なんだろう。System.Int32と書くより、intと書いた方が楽だからかな?とりあえず関数を選ぶときに別名は無視していいことが分かりました。
string とSystem.Stringも同じです。Usingで System が入っていると、全く同じ表記になります。
string a; String a;
といった変数定義になりますけど、どちらも同じって事ですね。別名を持つ変数の一覧と意味についてはこのサイトに分かりやすく一覧表にしてありました。
decimalを使う場合
コンピュータ内部では通常2進数で扱うところを、日常生活で使用する 10 進数を基数としています。このため表現できる桁数内なら、誤差は出ない仕様です。また、有効な桁数も多いため、特に小数の絡むお金の計算は double/float を避け、整数計算に持ち込むか、decimal 型で計算する事になります。
お金を扱う時にはdecimalと単純に考えていましたが、これで裏付けが取れました。
固定長変数、可変長変数のどちらを使うか
データベースの変数型を見ていると、固定長、可変長という言葉が出てきます。データベースの可変長変数の値を、プログラム上の変数で受ける時にどのような変数で受けるのが最適なのか。
データベースで言われる、固定か可変かの違いは、中に入るデータの長さが「固定」か「可変」かになります。中に入るデータの長さを調整する必要があるか否かがどちらを使いかのポイントになります。固定長変数(実際にはDBでいうカラムColumです。)には中に入るデータの長さがきまっています。
固定長変数は、入るデータの長さが決まっているので、無理やりにでもその長さにします。
可変長変数は、データの長さが決まっていないので最大の長さを超えない限りどんな長さのデータも受け入れます。
このため、データベースで固定長の変数を使うメリットは少ないという事になります。
しかーし、プログラムでの変数は固定・可変の区別は書いていません。
一覧表で見る限り、サイズはビット数が決まっています。つまり、C#で利用する変数はすべて固定長(メモリで占有するサイズが決まっている)という事で、変数によって浮動小数点が扱えるか、その変数に入る最大値をどこまで見込むのかがポイントになります。
Postgresの数値型は
Postgresの数値型種類は、10個あります。
型名 | 格納サイズ | 説明 | 範囲 |
---|---|---|---|
smallint | 2バイト | 狭範囲の整数 | -32768から+32767 |
integer | 4バイト | 典型的に使用する整数 | -2147483648から+2147483647 |
bigint | 8バイト | 広範囲整数 | -9223372036854775808から+9223372036854775807 |
decimal | 可変長 | ユーザ指定精度、正確 | 小数点前までは131072桁、小数点以降は16383桁 |
numeric | 可変長 | ユーザ指定精度、正確 | 小数点前までは131072桁、小数点以降は16383桁 |
real | 4バイト | 可変精度、不正確 | 6桁精度 |
double precision | 8バイト | 可変精度、不正確 | 15桁精度 |
smallserial | 2バイト | 狭範囲自動整数 | 1から32767 |
serial | 4バイト | 自動増分整数 | 1から2147483647 |
bigserial | 8バイト | 広範囲自動増分整数 | 1から9223372036854775807 |
では、Postgres numeric型はどのような性質か?
一覧表から見るところ、numericは桁数が131072桁あり、これが可変調(固定ではない)で入ります。さらに小数点が利用できます。
Postgresで数値演算(sum関数など利用した場合)すると、勝手にnumeric型になってくれて、可変長で少数も扱えるのでエラーなどが出る事もいという事です。
整数を利用する場合
smallintを利用するのは、占有するメモリ領域や、HDD領域を節約したい時に利用するものであり、最近のストレージ、メモリーの価格からすればほとんど利用機会はないのではないでしょうか。整数しか利用しないのであれば、integer型、integerで扱いきれない-2147483647 〜 +2147483647の範囲を超える(1億を超える値がを扱う)値を利用する場合はbigintを利用する事になります。
浮動小数点を利用する場合
Postgresの小数点の扱いは、numericが可変長なので、これで決まりだと思います。値の大きさに縛られないし、大きさによってメモリ・HDDの占有量は変わってくれます。また、Postgresではnumericと、decimalでは違いがありません。
Postgresでnumeric指定になった値を C#の何の変数で受けるのがいいの?
これ、そもそも考え方が違いました。こういうところでプログラムセンスがないんだろうなと痛感します。上記の事を頭に入れて考えると、numericだから何の変数で受けるのかではなく、
計算結果は整数か?少数を含むか?
計算結果の最大値(最小値)は?
で判断すべきです。これが最適な結論につながります。
私の場合、sum計算させた値は、少数にはなりません。(ちなみにマイナスにもなりませんが)。なおかつ、-2147483647 〜 +2147483647を超える事もありません。なので、c#側の最適な変数はint型になります。