大家有没有在SQL中遇见1不等于1(1<>1)的情形!?下面会有一个例子演示这个情形。
先简单介绍一下标题中的四种数值数据类型。
在T-SQL中,numeric和decimal是精确数值数据类型,而float和real是近似数值数据类型。
numeric和decimal是等同的。real等同于float(24).
在定义一个float(n)类型列的时候,如果明确指定了n的值,例如
val float(10)
那么当n的值在1-24之间,系统会将该列(val)标记为real类型;当n的值在25-53之间,系统会将该列标记为float类型。从系统表sys.columns可以得到验证。
如果没有明确指定,n的默认值是53. 补充一下,因为float类型的值是使用科学计数法表示的,所以n表示值的有效位数,MSDN表述n为数值尾数的位数。
现在来看具体的示例。
1 CREATE TABLE TMAIN( 2 id INT IDENTITY(1,1) PRIMARY KEY, 3 val FLOAT 4 ) 5 GO 6 7 CREATE TABLE TDETAIL( 8 id INT IDENTITY(1,1) PRIMARY KEY, 9 pid INT, 10 val FLOAT 11 ) 12 GO 13 14 INSERT INTO TMAIN VALUES(100); 15 INSERT INTO TMAIN VALUES(100); 16 17 INSERT INTO TDETAIL VALUES(1, 30); 18 INSERT INTO TDETAIL VALUES(1, 35); 19 INSERT INTO TDETAIL VALUES(1, 35); 20 21 INSERT INTO TDETAIL VALUES(2, 30); 22 INSERT INTO TDETAIL VALUES(2, 30); 23 INSERT INTO TDETAIL VALUES(2, 40); 24 25 --SELECT * FROM TMAIN; 26 --SELECT * FROM TDETAIL; 27 28 SELECT TM.id, SUM(TM.val * TD.val) / 10000.0 AS SUMPER 29 FROM TMAIN TM INNER JOIN TDETAIL TD ON TM.id = TD.pid 30 GROUP BY TM.id 31 32 SELECT TM.id, SUM(TM.val * TD.val) / 10000.0 AS SUMPER 33 FROM TMAIN TM INNER JOIN TDETAIL TD ON TM.id = TD.pid 34 GROUP BY TM.id 35 36 SELECT * 37 FROM ( 38 SELECT TM.id, SUM(TM.val * TD.val / 10000.0) AS SUMPER 39 FROM TMAIN TM INNER JOIN TDETAIL TD ON TM.id = TD.pid 40 GROUP BY TM.id 41 ) TMS 42 WHERE TMS.SUMPER = 1; 43 44 SELECT * 45 FROM ( 46 SELECT TM.id, SUM(TM.val * TD.val) / 10000.0 AS SUMPER 47 FROM TMAIN TM INNER JOIN TDETAIL TD ON TM.id = TD.pid 48 GROUP BY TM.id 49 ) TMS 50 WHERE TMS.SUMPER = 1; 51 52 DROP TABLE TMAIN; 53 DROP TABLE TDETAIL;
没执行之前,要不要预测一下结果?
先看一下前二个SELECT语句的执行结果。
第一个SELECT
id | SUMPER |
1 | 1 |
2 | 1 |
第二个SELECT
id | SUMPER |
1 | 1 |
2 | 1 |
结果是一样的,至少,看上去一样的!
再看一下后两个SELECT语句的执行结果。
第三个SELECT
id | SUMPER |
2 | 1 |
第四个SELECT
id | SUMPER |
1 | 1 |
2 | 1 |
后两个SELECT的结果产生了差异:一个是先乘除,后加减;另一个是先加减,后乘除。
因为val列是float类型,是近似数值数据类型,所以很明显,第一个SELECT的结果中有一行数据在计算过程中产生了近似值1. 而WHERE语句中指定的1,默认是int类型,int类型是精确数据类型。所以第三个SELECT语句出现了1<>1的情形。
举例完毕。
如果将val列定义成decimal类型,上面四个SELECT语句的结果是一样的。建议谨慎使用近似数值数据类型,并且在计算和比较值的时候,预见潜在的问题。
时间: 2024-10-18 09:37:09