none
getInt32とGetDecimal の使いわけについて RRS feed

  • 質問

  • お世話になっております、yanazakiと申します。
    質問の場所が違いましたらご容赦ください。

    あるODBC I/F プログラムの数値型取得で、
    下記の例外がイベントに出力されました。
    --
    System.InvalidCastException: 指定されたキャストは有効ではありません。
    場所 System.Data.SqlClient.SqlBuffer.get_Int32()
    --
    しかし、検証の結果、以下の挙動をしていてモヤモヤしています。

     ・使用ドライバが「Native Client 11」では発生せず、
       「ODBC Driver 13」で発生した。

     ・「ODBC Driver 13」でも、getInt32からGetDecimal に変更したら
      正常に取得できるようになった。
      ただし、getInt32 でも正常に取得できる場合もある。

    つきましては、以下ご存じの方がいらっしゃいましたら、
    ご教授をいただけませんでしょうか。

    ------------------------------------------------
    (1) getInt32と、GetDecimalの使い分けはどのようになるのでしょうか。

    (2) (1)は、ドライバごとに仕様が異なるのでしょうか。
    ------------------------------------------------

    ※  Oracle の情報を一般のHPで見ますと、以下の記載がありますが、
      SQLServerでも以下があてはまるのか気になっています。

          NUMBER(9)までだったらgetInt32で問題なく取得できるのだが、
          NUMBER(10)を超えるとgetDecimalを使わないと・・ 

    乱文・長文で恐縮ですが、何卒よろしくお願い致します。

    2018年10月30日 2:40

回答

  • ただし、getInt32 でも正常に取得できる場合もある。

    取得元のフィールドのデータ型を確認してみてください。

    もしもテーブルやビューの列として取得するのではなく、
    SQL 中で数値リテラルを記述していた場合には、
    表記法によってデータ型が異なります。たとえばこんな具合に。

    123     → INT
    123.    → NUMERIC(3,0)
    123.0   → NUMERIC(4,1)
    $123.0  → MONEY
    1.23E+1 → FLOAT
    0x0123  → VARBINARY
    
    • 回答としてマーク yanazaki 2018年10月31日 2:48
    2018年10月30日 8:56

すべての返信

  • System.Data.SqlClient.SqlDataReader.GetInt32 メソッド
    System.Data.Odbc.OdbcDataReader.GetInt32 メソッド

    の事でよろしいでしょうか。

    (1) getInt32と、GetDecimalの使い分けはどのようになるのでしょうか。

    返却された値が 整数型の場合に前者を用います。

    たとえば SQL Server 上に下記テーブルがあれば、
    GetInt32(0) は成功しますが、GetInt32(1~9) は失敗します。
    GetDecimal(1~7) は成功しますが、GetDecimal(0) や GetDecimal(8~9) は失敗します。
    GetDouble(8) は成功しますが、GetDouble(0~7) や GetDouble(9) は失敗します。
    GetFloat(9) は成功しますが、GetFloat(0~8) は失敗します。

    同様に、GetSqlInt32(0)、GetSqlDouble(8)、GetSqlSingle(9) 等は成功します。

    CREATE TABLE [TBL]
    ( [F0] int
    , [F1] numeric(2, 0)
    , [F2] numeric(9, 0)
    , [F3] numeric(10, 0)
    , [F4] numeric(5, 3)
    , [F5] decimal(8, 0)
    , [F6] decimal(9, 0)
    , [F7] decimal(5, 3)
    , [F8] float
    , [F9] real
    )

    2018年10月30日 3:22
  • ただし、getInt32 でも正常に取得できる場合もある。

    取得元のフィールドのデータ型を確認してみてください。

    もしもテーブルやビューの列として取得するのではなく、
    SQL 中で数値リテラルを記述していた場合には、
    表記法によってデータ型が異なります。たとえばこんな具合に。

    123     → INT
    123.    → NUMERIC(3,0)
    123.0   → NUMERIC(4,1)
    $123.0  → MONEY
    1.23E+1 → FLOAT
    0x0123  → VARBINARY
    
    • 回答としてマーク yanazaki 2018年10月31日 2:48
    2018年10月30日 8:56
  • 魔界の仮面弁士様

    質問者のyanazkaiです。
    本件、わかりやすいご回答をありがとうございます。

    「Native Client 11」でなぜ正常動作したのか謎ですが、
    正式には使用致しませんので、ODBC13にて
    ご回答のように型を整理したいと思います。

    2018年10月31日 2:48