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

我应该绑定什么数据类型作为查询参数,以便与Oracle ODBC中的数字(15)列一起使用?,c,oracle,odbc,C,Oracle,Odbc,我刚刚被问题中描述的问题所困扰 我正在使用ODBC 2将一个C/C++应用程序从SQL Server移植到Oracle。对于超过数字(9)的数字字段,它使用u int64数据类型,该数据类型作为SQL_C_SBIGINT绑定到查询。显然,Oracle ODBC不支持这种绑定。我现在必须在应用程序范围内转换到另一种方法。因为我没有太多时间——这是一个意想不到的问题——我宁愿使用经过验证的解决方案,而不是反复试验 应该使用什么数据类型来绑定,例如Oracle中的数字(15)?是否有书面建议的解决方案

我刚刚被问题中描述的问题所困扰

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

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

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


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

SQL\u C\u CHAR

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

我不明白为什么我应该在SQL INSERT或UPDATE命令中使用显式转换(例如,TO_NUMERIC)。当我将参数绑定为C类型的SQL_C_CHAR和SQL_NUMERIC(具有适当的精度和比例)作为SQL类型时,一切正常。我无法重现任何数据损坏效果

SQL\u数值结构

我注意到ODBC 3.0中添加了SQL\u NUMERIC\u STRUCT,并决定尝试一下。我很失望

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

SQL_NUMERIC_STRUCT具有所有必需的字段,以精确和比例表示任何数字(或数字或十进制)值。只是它们没有被使用

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

在编写时,Oracle感谢地尊重SQL\u NUMERIC\u STRUCT中包含的scale。但是ODBC规范没有强制要求它,MS SQL Server忽略了这个值。所以,再次回到SQLSetDescField

有关更多信息,请参阅和

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



我想我会使用SQL_C_CHAR。

我个人的偏好是将绑定变量设置为字符串(VARCHAR2),并让Oracle将字符转换为自己的内部存储格式。很容易(在C语言中)以可接受的格式获取以null结尾的字符串表示的数据值

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

SET MY_NUMBER_COL = :b1
  , MY_DATE_COL = :b2
SET MY_NUMBER_COL = TO_NUMBER( :b1 )
  , MY_DATE_COL   = TO_DATE( :b2 , 'YYYY-MM-DD HH24:MI:SS')
我这样编写SQL:

SET MY_NUMBER_COL = :b1
  , MY_DATE_COL = :b2
SET MY_NUMBER_COL = TO_NUMBER( :b1 )
  , MY_DATE_COL   = TO_DATE( :b2 , 'YYYY-MM-DD HH24:MI:SS')
并提供字符串作为绑定变量

这种方法有几个优点

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

另一个优点是,在Oracle事件10046跟踪上,绑定值更容易破译

此外,解释计划(我相信)要求所有绑定变量都是VARCHAR2,因此这意味着被解释的语句与实际执行的语句略有不同(因为当实际语句中绑定参数的数据类型不是VARCHAR2时会进行隐式数据转换)

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

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

基于过去的经验,这只是我个人的偏好


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

看起来它在oracle和MS SQL Server上都能工作。我担心oracle可能会以科学(指数)形式返回数字表示法。但从我所看到的情况来看,它通常返回数字。唯一的模棱两可之处是小数点分隔符和符号位置——必须注意区域设置。顺便说一句,asktom.oracle.com说:“对不起,我现在有大量积压工作,请稍后再问问题。”我选择了这个答案,尽管它没有给出明确的答案,因为我最终绑定了数字的char*表示。但是,与答案中提出的不同,我没有在查询本身中使用任何强制转换。我只是将SQL_C_char绑定为C类型,将SQL_NUMERIC绑定为SQL类型,并且它可以工作。对于日期等,我认为它是ODBC驱动程序(不是RDMBS)这就解决了转换问题。这是一个非常好的问题。我一直在想,ODBC设计人员是否有合理的理由做出这样的决定,或者他们只是去吃午饭,忘记了完成这个部分?很遗憾,没有人能够提供答案。