计算列相关问题的讨论
2010-04-07 11:44
232 查看
所谓计算列,即其值不是独立指定的,而是由其余列值计算出来的列。比如平均成绩就是一个典型的计算列。下面简单讨论下使用计算列过程中所需注意的一些问题。环境:SQL Server 2000,VC++ 2008 SP1,ATL OLE DB。
计算列可能在两种不同的情形中出现:一是出现在CREATE TABLE时列的定义里,一是出现在SELECT语句中。先讨论第一种情形。
在CREATE TABLE中定义计算列时,你是不能定义其类型的。那么计算列的类型到底是什么呢?下面是我的实验结果:1、表中有3列。前两列A、B是INT,而第三列C被定义成一个(A + B) / 2的计算列。此时,C的类型为INT。如果除不尽,则如同C/C++中一样进行截断取整。2、C定义成(A + B) / 2.0。此时C为NUMERIC类型。3、只要A、B中有REAL或FLOAT型,则无论C使用2还是2.0,它的类型都取A、B中表示范围更广的那一个(即FLOAT)。再顺带提一个创建视图时的问题。如果视图中包含计算列,则必需在视图名后指定列名,而不能企图在SELECT子句里对计算列命名(对于从多张表中选取同名列时,在SELECT子句里命名是可行的)。另外,在对包含计算列的表进行INSERT时,不能给计算列赋值且无需在表名后面指定欲赋值的列以显式排除计算列,直接在VALUES里面包含非计算列的值即可。
在SELECT语句中也经常会涉及计算列,比如SELECT val * 0.75。那么SELECT出的结果的类型又是什么呢?使用CDynamicAccessor::GetColumnType进行实验得出了如下结果:考虑SELECT val * x。1、val为INT,x为整数时,结果为INT。2、x为小数时,结果为NUMERIC。3、val为FLOAT或REAL时,无论x为整数还是小数,结果都为val的类型。
由此,我们似乎可以得出这样的结论:当已知信息足够确定结果类型时,系统根据已知信息确定数据类型(取表示范围最大的那个),否则默认使用NUMERIC(NUMERIC可以表示的范围最大)。
最后再讨论下C++中如何处理NUMERIC类型。CDynamicAccessor默认情况下将NUMERIC映射成DB_NUMERIC结构。该结构在oledb.h中的定义如下:
DB_NUMERIC仅数值部分就占16个字节,其表示能力可见一斑。下面用代码示例将DB_NUMERIC转换为double类型的一个方法。当然,转换过程中可能丢失精度。
注意unsigned long long在x86上一般只占8个字节(64位),所以在转换过程中由于表示范围的差异而出现问题是完全可能的,应特别留意。
计算列可能在两种不同的情形中出现:一是出现在CREATE TABLE时列的定义里,一是出现在SELECT语句中。先讨论第一种情形。
在CREATE TABLE中定义计算列时,你是不能定义其类型的。那么计算列的类型到底是什么呢?下面是我的实验结果:1、表中有3列。前两列A、B是INT,而第三列C被定义成一个(A + B) / 2的计算列。此时,C的类型为INT。如果除不尽,则如同C/C++中一样进行截断取整。2、C定义成(A + B) / 2.0。此时C为NUMERIC类型。3、只要A、B中有REAL或FLOAT型,则无论C使用2还是2.0,它的类型都取A、B中表示范围更广的那一个(即FLOAT)。再顺带提一个创建视图时的问题。如果视图中包含计算列,则必需在视图名后指定列名,而不能企图在SELECT子句里对计算列命名(对于从多张表中选取同名列时,在SELECT子句里命名是可行的)。另外,在对包含计算列的表进行INSERT时,不能给计算列赋值且无需在表名后面指定欲赋值的列以显式排除计算列,直接在VALUES里面包含非计算列的值即可。
在SELECT语句中也经常会涉及计算列,比如SELECT val * 0.75。那么SELECT出的结果的类型又是什么呢?使用CDynamicAccessor::GetColumnType进行实验得出了如下结果:考虑SELECT val * x。1、val为INT,x为整数时,结果为INT。2、x为小数时,结果为NUMERIC。3、val为FLOAT或REAL时,无论x为整数还是小数,结果都为val的类型。
由此,我们似乎可以得出这样的结论:当已知信息足够确定结果类型时,系统根据已知信息确定数据类型(取表示范围最大的那个),否则默认使用NUMERIC(NUMERIC可以表示的范围最大)。
最后再讨论下C++中如何处理NUMERIC类型。CDynamicAccessor默认情况下将NUMERIC映射成DB_NUMERIC结构。该结构在oledb.h中的定义如下:
typedef struct tagDB_NUMERIC { BYTE precision; // 精度,即最大有效数字位数 BYTE scale; // 小数位数,叫标度来着? BYTE sign; // 符号标志。1为正,0为负 BYTE val[ 16 ]; // 数值。低位在前。 } DB_NUMERIC; // 详情参考MSDN : )
DB_NUMERIC仅数值部分就占16个字节,其表示能力可见一斑。下面用代码示例将DB_NUMERIC转换为double类型的一个方法。当然,转换过程中可能丢失精度。
DB_NUMERIC v = *(DB_NUMERIC*)command.GetValue(1); double dVal = *(unsigned long long*)v.val / pow(10.0, (double)v.scale); if (!v.sign) { dVal = -dVal; }
注意unsigned long long在x86上一般只占8个字节(64位),所以在转换过程中由于表示范围的差异而出现问题是完全可能的,应特别留意。
相关文章推荐
- 【讨论】为啥0.2+0.4 != 0.6(浮点数计算的精度问题)
- 用 MapReduce 解决与云计算相关的 Big Data 问题
- 讨论c/c++计算小数的精度问题
- [导入]国内一些不错的PDF相关问题讨论的论坛
- Android--焦点问题以及讨论事件传递机制问题(结合部分相关源码)
- 【并行计算-CUDA开发】有关CUDA当中global memory如何实现合并访问跟内存对齐相关的问题
- 总结利用秩为1的矩阵相关矩阵的秩的计算问题
- 讨论c/c++计算小数的精度问题
- 无法处理内核页面请求的虚拟地址(相关问题讨论)
- Python cookbook(数据结构与算法)字典相关计算问题示例
- TI论坛上的ZigBee相关问题讨论
- 关于NP,NP-hard,P,NPC等相关问题的讨论
- 关于NP,NP-hard,P,NPC等相关问题的讨论【转帖】
- 讨论一个MQ的相关问题
- Cache – 主存的地址映射及相关计算问题
- 建了一个"symbina 技术"邮件列表,欢迎大加入到这个群,讨论symbian C++相关的技术问题!
- php时间计算相关问题小结
- php时间计算相关问题小结
- 主要讨论hadoop相关的问题
- Ruby的字符串与数组求最大值的相关问题讨论