前言

  前些天成功的连接并简单操作了一下数据库,谁知在第二天做些小动作的时候却碰到了不小的麻烦,就是数据库中标记为Decimal或者Numeric的数据都读取不了,这可就麻烦大了,先后在SQLGetData中换了SQL_C_DOUBLE、SQL_C_FLOAT两种种类型都无功而返,直到后来发现了,还有SQL_C_NUMERIC这个东西,一瞬间就很兴奋,结果照着MSDN的介绍使用了,还是不大行。

改变

  后来就继续查资料了,结果在stackflow上面找到了一篇很好的文章(牛人果然多呀),正好是介绍这一点的,MSDN也还是非常强大的:

    http://support.microsoft.com/kb/222831

  简单来说,核心的地方就是在执行完SQL语句后,要设置数据的属性,具体的代码如下:

  /* 这一部分和上面一样 */      SQLRETURN l_uiReturn = SQLAllocHandle(SQL_HANDLE_STMT,m_hDatabaseConnection,&m_hStatement);if (l_uiReturn != SQL_SUCCESS && l_uiReturn != SQL_SUCCESS_WITH_INFO){return l_oRetval;}CString l_cstrSql;l_cstrSql.Format(_T("SELECT [float] FROM [数据源名称].[所属者].[data] ORDER BY [float] DESC"));l_uiReturn = SQLExecDirect(m_hStatement,l_cstrSql.GetBuffer(),SQL_NTS);if (l_uiReturn != SQL_SUCCESS && l_uiReturn != SQL_SUCCESS_WITH_INFO){return l_oRetval;}/* 该代码段用于配置当前语句相关数据列的数据格式 */ //这里开始进入重点 #pragma regionSQLHDESC l_hDesc; //第四种句柄出现了l_uiReturn = SQLGetStmtAttr(m_hStatement, SQL_ATTR_APP_ROW_DESC,&l_hDesc, 0, NULL);//获得SQL语句的属性if (l_uiReturn != SQL_SUCCESS && l_uiReturn != SQL_SUCCESS_WITH_INFO){return l_oRetval;}/* Float数据格式,对应数据库中设置格式为DECIMAL(5,2) */l_uiReturn = SQLSetDescField (l_hDesc,1,SQL_DESC_TYPE,(VOID*)SQL_C_NUMERIC,0);l_uiReturn = SQLSetDescField (l_hDesc,1,SQL_DESC_PRECISION,(VOID*) 5,0);l_uiReturn = SQLSetDescField (l_hDesc,1,SQL_DESC_SCALE,(VOID*) 2,0);
#pragma endregionl_uiReturn = SQLFetch(m_hStatement);if (l_uiReturn != SQL_SUCCESS && l_uiReturn != SQL_SUCCESS_WITH_INFO){return l_oRetval;}SQL_NUMERIC_STRUCT l_tFloat;SQLINTEGER l_siLength = 0;/* 获得相应的浮点数形数据 */SQLGetData(m_hStatement,1,SQL_ARD_TYPE,&l_tFloat,sizeof(l_tFloat),&l_siLength);  //这里一定要使用SQL_ARD_TYPE,意思是要使用我们上面设置好的数据格式  SQLFreeHandle(SQL_HANDLE_DESC,l_hDesc);SQLFreeHandle(SQL_HANDLE_STMT,m_hStatement);

  然后调试,开始看l_tFloat中的数据,结果发现基本上不懂,所以还是继续看文章吧,在其下方建立了一个函数,负责数据转化,所以重写了一个自己的版本并理解了一下,简单的来说,这是一个16进制浮点数据转化的过程:

double GetDoubleFromHexStruct(SQL_NUMERIC_STRUCT & p_rtNumeric)
{long l_lValue =0;int l_iLastVal = 1,l_iCurrentVal = 0;int l_iLsd = 0 ,l_iMsd = 0;for(int i = 0;i < 16 != 0;i++){l_iCurrentVal = (int) p_rtNumeric.val[i];l_iLsd = l_iCurrentVal % 16;l_iMsd = l_iCurrentVal / 16;l_lValue += l_iLastVal * l_iLsd;    l_iLastVal = l_iLastVal * 16;    l_lValue += l_iLastVal * l_iMsd;l_iLastVal = l_iLastVal * 16;    }long l_lDivisor = 1;for (int i =0;i < p_rtNumeric.scale;i++){l_lDivisor = l_lDivisor * 10;}return (double)(l_lValue/(double)l_lDivisor);}

  将l_tFloat经过这个函数就可以顺利得到我们想要的值了,虽然在数值上会有差距,但基本上是由于计算机表达浮点数的误差导致的,这个就谁也没办法了。

思考

  可以看到,其实上面的代码还是挺复杂的,尤其是当面对不停的用户需求变化,这种方式简直就有点像在自杀,每个固定的SQL语句的地方都要进行修改,虽然现在维护的程序需要数据库的方面较少,但是抱着未雨绸缪的思想,还是提前准备一下比较好,结果就是,没准备出来。按说ODBC API已经被MFC给面向对象过了,理论上是肯定可以实现的,但奈何自己还是没那个本事,当时是因为看上了SQLGetDescField这个函数,我就想看一看到底能否获得数据格式,按说由于数据库这些设计虽然不一定让改,但是查询数据格式的功能应该是向外提供的,但是弄了半天,这个函数一直返回一个SQL_NO_DATA的错误,整整一个下午的时间也没弄明白。

  总的来说,自己还是对数据库的知识不扎实,MSDN上的长篇描述也是让自己很头疼,希望如果有了解这方面的人可以告诉我一下,我也想简单的封装一下API,以此来熟悉数据库的驾驭方式。

转载于:https://www.cnblogs.com/geminiv/archive/2012/09/21/2697264.html

使用ODBC API读取Decimal或者Numeric相关推荐

  1. ODBC API 学习总结

    ODBC 编程API http://blog.csdn.net/bichenggui/article/details/5601381 转的ODBC API函数详细说明. 看了一遍,没有问题. 使用 O ...

  2. mysql:列类型之decimal、numeric

    环境: window10 vs2022 .net 6 mysql 8.0.25 DBeaver 参考: <mysql:11.1.3 Fixed-Point Types (Exact Value) ...

  3. 使用Hybris Commerce User API读取用户信息时,电话字段没有返回

    在使用Hybris Commerce User API读取一个user信息时,我遇到一个问题,在API返回的结构里没有包含期望看到的Phone字段. 仔细观察Swagger里对response结构的说 ...

  4. HTML5 file api读取文件的MD5码工具

    1.工具的用途:用HTML5 file api读取文件的MD5码.MD5码在文件的唯一性识别上有很重要的应用,业内常用MD5进行文件识别.文件秒传.文件安全性检查等: 2.适用性:IE.Chrome皆 ...

  5. 使用J2SE API读取Properties文件的六种方法(选择自 kindani 的 Blog )

    使用J2SE API读取Properties文件的六种方法 1.使用java.util.Properties类的load()方法 示例: InputStream in = lnew BufferedI ...

  6. numeric mysql_MYSQL的DECIMAL和NUMERIC类型

    MYSQL, DECIMAL和NUMERIC类型 说明: DECIMAL和NUMERIC类型在MySQL中视为相同的类型.它们用于保存必须为确切精度的值,例如货币数据. 当声明该类型的列时,可以(并且 ...

  7. numeric mysql_MySQL数据类型-decimal与numeric的区别

    1.首先,对于精度比较高的东西,比如money,我会用decimal类型,不会考虑float,double,因为他们容易产生误差,numeric和decimal同义,numeric将自动转成decim ...

  8. decimal 和 numeric

    GPS平台.网站建设.软件开发.系统运维,找森大网络科技! https://cnsendnet.taobao.com 来自森大科技官方博客 http://www.cnsendblog.com/inde ...

  9. Flink 使用Table Api 读取文件数据并写出到文件中

    前言 在上一篇我们演示了如何使用Flink 的Table Api 读取文件数据,并过滤特定字段的数据,本篇在上一篇的基础上,将从CSV文件中读取的数据重新输出到一个新的CSV文件中: 在实际业务场景下 ...

  10. SQL Server decimal 和 numeric 区别

    最近看到了decimal 和 numeric ,又记不起来区别是什么,还是总结一下. decimal 和 numeric 在 SQL 标准中可以说是等价的的,在SQL Server 中是一样的(参考: ...

最新文章

  1. python 3元运算符
  2. 千万不要把 bool 当成函数参数
  3. 输入三个字符串按由小到大输出
  4. Linux0.11中对文本文件进行修改的策略
  5. linux内核网络协议栈--数据包的skb桥转发蓝图(二十六)
  6. LeapMotion使用入门
  7. oracle中的cursor属性有哪些,Cursor语法及理解
  8. C++基本数据类型解惑
  9. java new 面试_java面试30问
  10. 作者:孟磊,山东省农业信息中心助理农经师。
  11. lightoj 1236 正整数唯一分解定理
  12. 怎么找网页源文件位置_原神白铁块位置分布图 原神白铁块怎么找
  13. linux中telnet工具,linux中telnet工具的介绍和使用
  14. java word书签_JAVA 创建移除Word书签
  15. 凛冬已至:大厂裁员浪潮,基础福利大砍,行业饱和,大龄程序员该如何自处
  16. 同花顺没签三方要赔钱才能拿回三方!!!!
  17. 【萌新笔记】简单记录“智能管家”的设计过程
  18. 自媒体短视频怎么玩?0粉丝也可以变现,5种变现模式
  19. 计算机蓝屏代码0xc0000020,Win10运行程序提示“损坏的映像 错误0xc0000020”解决方法图文教程...
  20. [读书笔记] 用户增长方法论

热门文章

  1. python基础:pip和虚拟环境
  2. 19年春第十五周学习
  3. java为什么使用TypeReference
  4. 那些年做过的ctf之加密篇
  5. Form,你到底是客户端还是服务端
  6. WLC HA (for AP)?
  7. 现代软件工程——第一周博客作业
  8. ERROR 1045 (28000): Access denied for user 'admin'@'localhost' (using password: YES)
  9. CoreData 增删改查
  10. jquery_datatables