我应该将哪种数据类型绑定为查询参数以与Oracle ODBC中的NUMBER(15)列一起使用?

我刚刚被SO问题Binding int64(SQL_BIGINT)中描述的问题所困扰,因为查询参数在Oracle 10g ODBC中执行期间会导致错误 。

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

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

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


到目前为止我尝试了什么:

SQL_C_CHAR

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

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

SQL_NUMERIC_STRUCT

我注意到SQL_NUMERIC_STRUCT添加了ODBC 3.0并决定尝试一下。 我很失望。

在我的情况下,这已经足够了,因为应用程序并不真正使用小数。 但作为一般解决方案……简单地说,我不明白。 我的意思是,我终于理解了应该如何使用它。 我没有得到的是: 为什么有人会引入这种新结构,然后以这种方式工作

SQL_NUMERIC_STRUCT具有表示任何NUMERIC(或NUMBER或DECIMAL)值及其精度和比例所需的所有字段。 只有它们不被使用。

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

在编写时,Oracle非常感谢尊重SQL_NUMERIC_STRUCT中包含的规模。 但ODBC规范并未强制要求它,MS SQL Server会忽略此值。 所以,再次回到SQLSetDescField。

请参阅HOWTO:使用SQL_NUMERIC_STRUCT和INF 检索数字数据 :如何将SQL_C_NUMERIC数据类型与数字数据一起使用以获取更多信息。

为什么ODBC没有完全使用自己的SQL_NUMERIC_STRUCT? 我不知道。 看起来它有效,但我认为这只是太多的工作。


我想我会使用SQL_C_CHAR。

我个人的偏好是使绑定变量字符串(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') 

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

这种方法有几个优点。

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

另一个优点是绑定值更容易在Oracle事件10046跟踪上进行解密。

另外,EXPLAIN PLAN(我相信)期望所有绑定变量都是VARCHAR2,这意味着所解释的语句与正在执行的实际语句略有不同(由于实际绑定参数的数据类型时隐式数据转换语句不是VARCHAR2。)

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

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

根据过去的经验,这只是个人偏好。 我使用与Perl DBD相同的方法。

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