代码之家  ›  专栏  ›  技术社区  ›  Tomek Szpakowicz

我应该绑定什么数据类型作为查询参数来与Oracle ODBC中的数字(15)列一起使用?

  •  4
  • Tomek Szpakowicz  · 技术社区  · 14 年前

    我刚刚被问题中描述的问题咬伤了 Binding int64 (SQL_BIGINT) as query parameter causes error during execution in Oracle 10g ODBC .

    我正在使用SQL数据库到Oracle的ODBC 2移植C/C++应用程序。对于超过数字(9)的数字字段,它使用uu int64数据类型,该数据类型绑定到查询中作为SQL_c_sbigit。显然,Oracle ODBC不支持这种绑定。我现在必须在应用程序范围内转换为另一种方法。因为我没有太多的时间——这是一个意想不到的问题——我宁愿使用经过验证的解决方案,而不是尝试和错误。

    应使用哪种数据类型进行绑定,例如Oracle中的数字(15)? 是否有书面建议的解决方案?你在用什么?有什么建议吗?

    我对不需要任何额外转换的解决方案特别感兴趣。我可以很容易地以uu int64或char*的形式提供和使用数字(正常 非指数 不带千位分隔符或小数点的窗体)。任何其他格式都需要我进行额外的转换。


    到目前为止我所做的尝试:

    平方英尺

    看起来对我有用。我担心数字格式的可变性。但在我的用例中,这似乎并不重要。显然只有分数字符随系统语言设置而改变。

    我不明白为什么我应该在sql insert或update命令中使用显式强制转换(例如to_numeric)。当我用SQL_char作为C类型和SQL_numeric(具有适当的精度和比例)作为SQL类型绑定参数时,一切都可以正常工作。我无法复制任何数据损坏效果。

    SQL数字结构

    我注意到了添加了odbc 3.0的SQL数字结构,并决定尝试一下。我很失望。

    在我的情况下,这就足够了,因为应用程序实际上并不使用分数。但作为一个普遍的解决方案…简单地说,我不明白。我的意思是,我终于明白应该如何使用它了。我不明白的是: 为什么有人会引入这种新结构,然后让它以这种方式工作? .

    SQL数字结构具有所有必需的字段,可以用它的精度和小数位数表示任何数字(或数字或十进制)值。只是它们没有被使用。

    在读取时,ODBC设置数字的精度(基于列的精度;但Oracle返回更高的精度,例如数字(15)为20)。但是,如果列具有小数部分(比例>0),则默认情况下会截断该部分。要以正确的比例读取数字,您需要设置精度,并在获取数据之前使用sqlsetdescfield调用对自己进行缩放。

    在编写时,Oracle感谢地尊重SQL数字结构中包含的比例。但odbc规范并没有规定它,而ms-sql-server忽略了这个值。所以,再次返回到sqlsetdescfield。

    HOWTO: Retrieving Numeric Data with SQL_NUMERIC_STRUCT INF: How to Use SQL_C_NUMERIC Data Type with Numeric Data 更多信息。

    为什么ODBC没有完全使用它自己的SQL数字结构?我不知道。它看起来很管用,但我觉得工作太多了。


    我想我会用SQL字符。

    1 回复  |  直到 14 年前
        1
  •  2
  •   spencer7593    14 年前

    我个人的偏好是使用绑定变量字符串(varchar2),并让Oracle将字符转换为自己的内部存储格式。很容易(在C中)得到以可接受的格式表示为以空结束字符串的数据值。

    因此,不要像这样编写SQL:

    SET MY_NUMBER_COL = :b1
      , MY_DATE_COL = :b2
    

    我这样写SQL:

    SET MY_NUMBER_COL = TO_NUMBER( :b1 )
      , MY_DATE_COL   = TO_DATE( :b2 , 'YYYY-MM-DD HH24:MI:SS')
    

    并提供字符串作为绑定变量。

    这种方法有几个优点。

    一种是解决绑定其他数据类型时遇到的问题和错误。

    另一个优点是绑定值更容易在OracleEvent10046跟踪上解密。

    另外,一个explain计划(我相信)期望所有绑定变量都是varchar2,这意味着被解释的语句与正在执行的实际语句略有不同(由于当实际语句中的bind参数的数据类型不是varchar2时隐式的数据转换)。

    而且(不太重要)当我在toad中测试语句时,只需要在输入框中输入字符串就可以了,而不必在下拉列表框中修改数据类型。

    我还允许butin to_number和to_date函数验证数据。(至少在Oracle的早期版本中,我遇到了直接绑定日期值的问题,它绕过了(至少部分)有效性检查,并允许将无效的日期值存储在数据库中。

    这只是个人偏好,基于过去的经验。我对PerlDBD使用相同的方法。

    我想知道TomKyte(asktom.oracle.com)对这个话题有什么看法?