最近看到了decimal 和 numeric ,又记不起来区别是什么,还是总结一下。

decimal 和 numeric 在 SQL 标准中可以说是等价的的,在SQL Server 中是一样的(参考:decimal 和 numeric (Transact-SQL)),可以查看类型定义确认:

SELECT * FROM sys.types WHERE name IN('DECIMAL','NUMERIC')
SELECT * FROM sys.systypes WHERE name IN('DECIMAL','NUMERIC')

到底有什么不一样呢?有人在 SQL-92 标准中找出了微妙的描述。

in the SQL-92 standard, decimalisexactly as precise as declared, whilenumericisat least as precise as declared. In SQL Server both are exactly as precise as declared

decimal 完全和声明的一样精确;numeric  至少和声明的一样精确。在 sql server 中两者使用完全和声明的一样精确。但是没有例子,很难明白。事实上,不仅sql server 有这两个类型,其他满足 sql 标准的数据库都有。

SQL2003 标准中对两者的描述:

21) NUMERIC specifies the data typeexact numeric, with the decimalprecision and scale specified by the<precision> and <scale>.22) DECIMAL specifies the data typeexact numeric, with the decimal scalespecified by the <scale> and theimplementation-defined decimalprecision equal to or greater than thevalue of the specified <precision>.

这段描述比较清楚了,小数类型的定义格式为(P,S),即固定精度和小数位数;numeric  要求固定精度和小数位一样精确,小数位固定长度;而 decimal 不一定,可能会大于或等于固定精度P的长度,即小数位的长度在存储的时候比实际的长,只是我们看不到罢了。。

没有例子,描述确实看不懂。上面是 SQL 标准的描述,在 SQL Server 当然也不一样。

但不管怎样,在 SQL Server 中,两者类型(名称)不同,但可以说是一样的,用哪个都行!

示例测试:

--   DROP TABLE [dbo].[TypeTest]
CREATE TABLE [dbo].[TypeTest]([DecType] [decimal](18, 8) NOT NULL,[NumType] [numeric](18, 8) NOT NULL
) ON [PRIMARY]
GO

现在查看测试:

DECLARE @DecType DECIMAL(18,8)
SET @DecType = 3.1415926
SELECT * FROM TypeTest WHERE DecType=@DecType
SELECT * FROM TypeTest WHERE NumType=@DecType
GO
DECLARE @NumType NUMERIC(18,8)
SET @NumType = 3.1415926
SELECT * FROM TypeTest WHERE DecType=@NumType
SELECT * FROM TypeTest WHERE NumType=@NumType
GO

可以看到,两者传递的类型虽然不一样,但是并没有在内部进行转换,此时传递的参数将 decimal 和 numeric 当做相同的。

现在直接赋值查询:

SELECT * FROM TypeTest WHERE DecType=3.1415926
SELECT * FROM TypeTest WHERE NumType=3.1415926

可以看到,decimal 类型的没有隐式转换,而 numeric  则进行了类型转换。也就是说传递的 “3.1415926” 既不不是 decimal 类型,也不是 numeric  类型?因为以下的查询是没有隐式转换的。

SELECT * FROM TypeTest WHERE DecType=CONVERT(DECIMAL(20,10),3.1415926)
SELECT * FROM TypeTest WHERE DecType=CONVERT(NUMERIC(20,10),3.1415926)
SELECT * FROM TypeTest WHERE NumType=CONVERT(DECIMAL(20,10),3.1415926)
SELECT * FROM TypeTest WHERE NumType=CONVERT(NUMERIC(20,10),3.1415926)

“3.1415926”  到底是什么类型??

查看该数值类型:

SELECT SQL_VARIANT_PROPERTY(3.1415926,'BaseType') AS [BaseType]
,SQL_VARIANT_PROPERTY(3.1415926,'Precision') AS [Precision]
,SQL_VARIANT_PROPERTY(3.1415926,'Scale') AS [Scale]

--------------------------------------------|

BaseType      Precision   Scale    |

----------          -------------  -----------|
numeric         8                7           |

------------------------------------------  |

可以看到,“3.1415926”  类型确实为 numeric,怎么一个需要隐式转换,一个不需要呢??当显如下sql式转换后查询,发现确实有隐式转换!

SELECT * FROM TypeTest WHERE DecType=CONVERT(NUMERIC(8,7),3.1415926)
SELECT * FROM TypeTest WHERE NumType=CONVERT(NUMERIC(8,7),3.1415926)

【渐渐地,越来越接近真相了…………】

现在转换成与精度一样的类型:

SELECT * FROM TypeTest WHERE DecType=CONVERT(NUMERIC(18,7),3.1415926)
SELECT * FROM TypeTest WHERE NumType=CONVERT(NUMERIC(18,7),3.1415926)

当固定精度为 18 时,没有发现需要隐式转换,即使小数位长度不一样。现在换成固定精度与字段定义的不一样看看。

SELECT * FROM TypeTest WHERE DecType=CONVERT(NUMERIC(17,7),3.1415926)
SELECT * FROM TypeTest WHERE NumType=CONVERT(NUMERIC(17,7),3.1415926)

好了,出现隐式转换了!!字段DecType类型(decimal )还是一样没什么影响,而 字段 NumTypel类型(numeric)出现了隐式转换!所以确定,类型 numeric 要求的固定精度大于等于声明的精度!

=====================================

接下来任意测试:

=====================================

故意设置较短的精度,可以看到数值 “321.1415926” 类型为 numeric。即传递的带小数位的数值,默认类型为numeric。

DECLARE @DecType DECIMAL(5,3)
SET @DecType = 321.1415926
GO
DECLARE @NumType NUMERIC(5,3)
SET @NumType = 321.1415926
GO

消息 8115,级别 16,状态 8,第 21 行
将 numeric 转换为数据类型 numeric 时出现算术溢出错误。
消息 8115,级别 16,状态 8,第 24 行
将 numeric 转换为数据类型 numeric 时出现算术溢出错误。

=====================================

将数据类型 decimal 和 numeric 都加上一个小数(如:3.14),发现 decimal  加上任意小时后,类型转变为 numeric 。

DECLARE @DecType DECIMAL(18,8)
DECLARE @NumType NUMERIC(18,8)
SET @DecType = 3.1415926
SET @NumType = 3.1415926SELECT SQL_VARIANT_PROPERTY(@DecType+3.14,'BaseType') AS [BaseType],SQL_VARIANT_PROPERTY(@DecType+3.14,'Precision') AS [Precision],SQL_VARIANT_PROPERTY(@DecType+3.14,'Scale') AS [Scale]SELECT SQL_VARIANT_PROPERTY(@NumType+3.14,'BaseType') AS [BaseType],SQL_VARIANT_PROPERTY(@NumType+3.14,'Precision') AS [Precision],SQL_VARIANT_PROPERTY(@NumType+3.14,'Scale') AS [Scale]

=====================================

对表创建外键,主外键类型不一样。可确定,decimal 和 numeric 类型是不一样的(本来就不一样,名字都不一样,哈哈!)

ALTER TABLE [TypeTest] ADD CONSTRAINT PK_TypeTest PRIMARY KEY([DecType])
GO
ALTER TABLE [TypeTest] ADD CONSTRAINT FK_TypeTest FOREIGN KEY([NumType]) REFERENCES [TypeTest]([DecType])
GO

消息 1778,级别 16,状态 0,第 13 行
列 'TypeTest.DecType' 的数据类型与外键 'FK_TypeTest' 中的引用列 'TypeTest.NumType' 的数据类型不同。
消息 1750,级别 16,状态 0,第 13 行
无法创建约束或索引。请参阅前面的错误。


最后总结:

数据类型 decimal 和 numeric 虽然在小数存储方面都一样,但建议使用Decimal(原因参考文章红色标注)

相关探讨:

SQLServer 唯一键约束和唯一索引有什么区别?

SQLServer 可变字符怎么设置长度?(如varchar)

SQL Server decimal 和 numeric 区别相关推荐

  1. SQL Server 与 ORACLE 的区别

    sql server 与  oracle的区别:    DBMS 数据库管理系统 1.数据类型不同.   sql server 的数据类型:int ,smallint ,char,varchar,nc ...

  2. SQL Server 2014各个版本区别

    SQL Server 2014各个版本区别 主要版本 SQL Server 版本 定义 Enterprise(64 位和 32 位) 作为高级版本,SQL Server 2014 Enterprise ...

  3. oracle stdevp函数,SQL Server与oracle两者区别之函数区别

    Oracle和SQL Server的常用函数对比 1.数学函数 ①绝对值 S:select abs(-1) value O:select abs(-1) value from dual ②取整(大) ...

  4. MySql和Sql Server语法和关键字区别

    1. MySQL支持enum,和set类型,SQL Server不支持 2. MySQL不支持nchar,nvarchar,ntext类型 3. MySQL的递增语句是AUTO_INCREMENT,而 ...

  5. MySQL8.0与SQL server 2016的技术区别(一)

    MySQL8.0与SQL server 2016都是关系型数据库,两者在原理与技术方面有极高的相似度.本文主要简述笔者在学习过程中发现的两者有区别的部分,如果读者知道还有其他区别的点,欢迎进行评论补充 ...

  6. sql server,mysql,oracle的区别

    Oracle Oracle 能在所有主流平台上运行(包括Windows).完全支持所有的工业标准.采用完全开放策略.可以使客户选择最适合的解决方案.对开发商全力支持,Oracle并行服务器通过使一组结 ...

  7. sql server decimal

    decimal不存在精度损失,数据类型decimal(p,s) 需要分别指定小数的最大位数(p)和小数位的数量(s): p (precision) :指定小数的最大位数,小数点的左侧和右侧的数字的总数 ...

  8. sqlserver中window身份验证跟sql server身份验证的区别

    1.集成的Windows身份验证语法 1 string constr = "server=.;database=myschool;integrated security=SSPI" ...

  9. SQL Server where和having区别

    where和having区别 where叙述 1.where子句实现分组之前过滤数据 2.where子句中不能包含聚合函数 having叙述 1.having子句实现分组后过滤数据 2.having子 ...

最新文章

  1. 转载的spring cloud的全家桶,有空学习下
  2. 数据结构与算法 整理笔记---二叉搜索树
  3. 分析对象内部结构,并详解synchronized锁膨胀升级和降级的过程
  4. AIX Study之--AIX网卡配置管理(ent0、en0、et0)
  5. linux系统下安装 Loadrunner11(个人感觉不错儿)
  6. C语言学习之试编程从键盘输入2*3的二维数组,将该数组行列交换输出。
  7. WPF整理-处理没有注意到的异常
  8. PHP自动测试框架Top 10
  9. # 遍历删除字典元素_第六章 字典
  10. .NET Core中间件的注册和管道的构建(1)---- 注册和构建原理
  11. 【渝粤教育】电大中专办公设备使用与维护 (2)_1作业 题库
  12. 课时27.base(掌握)
  13. 谷粒商城--API三级分类--网关统一配置跨域
  14. php将字符变为数字,数字字符怎么转化为数字 php 怎么将字符转成数字
  15. postman如何发送application/json类的post请求
  16. Python批量整理文件名小案例(附公众号第一批赠书活动中奖名单)
  17. Linux下MongoDB非正常关闭启动异常解决方法
  18. python分割出两幅图像重叠区域代码
  19. 常用的手机宽度 前端切图用 常用的手机尺寸
  20. WPS word表格中的神秘的底色

热门文章

  1. batocera笔记本调节亮度教程
  2. 通用数据保护条例GDPR今日起正式生效,不会影响机器学习
  3. c语言循环单链表实现约瑟夫环问题
  4. 密码(mima)的答案
  5. 2.5 信道的极限容量
  6. 【Docker】Docker安装
  7. viewpager切页
  8. 现下追求互动体验强的时代,企业展厅给客户传递更为全面的信息
  9. JavaSwing_4.1: JFrame(窗口)
  10. JSP与Servlet 基础知识