1不等于1?numericdecimalfloat 和 real 数据类型的区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1不等于1?numericdecimalfloat 和 real 数据类型的区别相关的知识,希望对你有一定的参考价值。

大家有没有在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语句的结果是一样的。建议谨慎使用近似数值数据类型,并且在计算和比较值的时候,预见潜在的问题。

以上是关于1不等于1?numericdecimalfloat 和 real 数据类型的区别的主要内容,如果未能解决你的问题,请参考以下文章

SQL语句查询不等于怎么查不出来?

为啥 [1,2,3] 在 Javascript 中不等于自身? [复制]

Excel IF函数中不等于怎么表示

mysql不等于符号怎么写

为啥“123”.split('') 不等于 [1, 2, 3].join('').split('') [重复]

我不明白为什么在此程序中a等于1,b等于0