1不等于1?numeric、decimal、float 和 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语句的结果是一样的。建议谨慎使用近似数值数据类型,并且在计算和比较值的时候,预见潜在的问题。

时间: 2024-10-18 09:37:09

1不等于1?numeric、decimal、float 和 real 数据类型的区别的相关文章

SqlServer中decimal(numeric )、float 和 real 数据类型的区别[转]

decimal(numeric )             同义,用于精确存储数值 float 和 real                      不能精确存储数值   decimal 数据类型最多可存储 38 个数字,所有数字都能够放到小数点的右边.decimal 数据类型存储了一个准确(精确)的数字表达法:不存储值的近似值. 定义 decimal 的列.变量和参数的两种特性如下: p   小数点左边和右边数字之和,不包括小数点.如 123.45,则 p=5,s=2. 指定精度或对象能够控

sql decimal &amp; float &amp; celling 介绍

decimal 可以用在指定几个位数比如 123.456, decimal(3,3), 用这类型计算比较准确. 默认情况下,将数字转换为较低精度和小数位数的 decimal 或 numeric 值时,SQL Server 会进行舍入 declare @number decimal(38,2) = 123.456; result = 123.46 float 可以默认是15个字节, 如果超出的了字节会舍入, 比如 1.999999999999991 = 1.99999999999999 1.999

MySQL中 DECIMAL FLOAT DOUBLE的区别

第一篇文章: MySQL中Decimal类型和Float Double等区别 MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型. 其区别在于,float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形式保存数值.float,double类型是可以存浮点数(即小数类型),但是float有个坏处,当你给定的数据是整数的时候,那么它就以整数给你处理.这样我们在存取货币值的时候自然遇到问题,我的default值为:0.00而实

float和double数据类型的声明,转换和计算

声明时,只要有小数部分float必须加F/f,而double却不用 //float的声明只要有小数部分就要加F,不然会报不能隐私的将double类型转换为float类型. float f1 = 1;//OK float f2 = 1.1F;//一定要F float f3 = 1.23F; //double声明不需要加D double d1 = 1; double d2 = 1.2; double d3 = 1.232434377777777; //double的精度高于float,double转

Java语言中:float、double数据类型在内存中是如何存储的

引用参考 https://www.cnblogs.com/chenmingjun/p/8415464.html#4291528 https://blog.csdn.net/yansmile1/article/details/70145416 java语言中,float类型数字在计算机中用4个字节(32位)来存储.double类型占用8个字节(64位). 从存储结构和算法上来讲,double和float是一样的,不一样的地方仅仅是float是32位的,double是64位的,所以double能存储

数据库高手(DBA专家 ,SSIS,replacation ,tourble shooting)

http://www.cnblogs.com/qanholas/category/266780.html 随笔分类 - mssql SQL Server 2008 Datetime Cast 成 Date 类型可以使用索引(转载) 摘要: 很久没写blog,不是懒,实在是最近我这的访问速度不好,用firefox经常上传不了图片 .......今天无意发现了SQL Server 2008 Datetime Cast 成 Date 类型可以使用索引,分享一下:测试环境:USETEMPDBGOCREA

Entity Framework(三):使用特性(数据注解)创建表结构

一.理解Code First及其约定和配置 传统设计应用的方式都是由下而上的,即我们习惯优先考虑数据库,然后使用这个以数据为中心的方法在数据之上构建应用程序.这种方法非常适合于数据密集的应用或者数据库很可能包含多个应用使用的业务逻辑的应用.对于这种应用,如果要使用EF的话,我们必须使用Database First方式. 设计应用的另一种方法就是以领域为中心的方式(领域驱动设计DDD).DDD是一种由上而下的方式,我们通过从实现应用所需要的领域模型和实体的角度思考,从而开始设计应用.数据库很少用来

Mysql中NUMERIC和DECIMAL类型区别比较

decimal(numeric ) 同义,用于精确存储数值 . decimal 数据类型最多可存储 38 个数字,所有数字都能够放到小数点的右边.decimal 数据类型存储了一个准确(精确)的数字表达法:不存储值的近似值. 定义 decimal 的列.变量和参数的两种特性如下: p 小数点左边和右边数字之和,不包括小数点.如 123.45,则 p=5,s=2.指定精度或对象能够控制的数字个数. s指定可放到小数点右边的小数位数或数字个数. p 和 s 必须遵守以下规则:0 <= s <= p

SQL SERVER 2008 nvarchar 转换 deciaml 失败(nvarchar to decimal)

转换数据发生 消息 8115,级别 16,状态 6,第 1 行 将 nvarchar 转换为数据类型 numeric 时出现算术溢出错误. nvarchar 是带很长小数,直接转换成decimal 失败 解决方案: 先转换成float 再转换成decimal 或者int(去掉小数位)   CAST(CAST(TRANS_CHARGE AS FLOAT) AS INT)   Why float? no idea of precision or scale across all rows: floa