您的位置:首页 > 其它

计算列相关问题的讨论

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中的定义如下:

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位),所以在转换过程中由于表示范围的差异而出现问题是完全可能的,应特别留意。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: