SqlServer数据库中decimal 和 numeric的区别是什么?

 更新时间:2019年3月15日 09:48  点击:1421

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 type

    exact numeric, with the decimal

    precision and scale specified by the

    <precision> and <scale>.


22) DECIMAL specifies the data type

    exact numeric, with the decimal scale

    specified by the <scale> and the

    implementation-defined decimal

    precision equal to or greater than the

    value 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.1415926

 

SELECT 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(原因参考文章红色标注)。

--------------------- 

作者:薛定谔的DBA 

来源:CSDN 

原文:https://blog.csdn.net/kk185800961/article/details/78853515 


[!--infotagslink--]

相关文章

  • C#中decimal保留2位有效小数的实现方法

    这篇文章主要介绍了C#中decimal保留2位有效小数的实现方法,针对decimal变量保留2位有效小数有多种方法,可以使用Math.Round方法以及ToString先转换为字符串等操作来实现。具体实现方法感兴趣的朋友跟随小编一起看看吧...2020-06-25
  • SQL Server中row_number函数的常见用法示例详解

    这篇文章主要给大家介绍了关于SQL Server中row_number函数的常见用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-12-08
  • C#查询SqlServer数据库并返回单个值的方法

    这篇文章主要介绍了C#查询SqlServer数据库并返回单个值的方法,涉及C#操作SQLServer数据库查询的相关技巧,需要的朋友可以参考下...2020-06-25
  • SQLServer 错误: 15404,无法获取有关 Windows NT 组/用户 WIN-8IVSNAQS8T7\Administrator 的信息

    SQLServer 错误: 15404,无法获取有关 Windows NT 组/用户 'WIN-8IVSNAQS8T7\Administrator' 的信息,错误代码 0x534。 [SQLSTATE 42000] (ConnIsLoginSysAdmin)...2021-07-15
  • SQL SERVER迁移之更换磁盘文件夹的完整步骤

    这篇文章主要给大家介绍了关于SQL SERVER迁移之更换磁盘文件夹的完整步骤,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-12-08
  • CentOS8安装SQLServer2019的过程

    这篇文章主要介绍了CentOS8安装SQLServer2019的步骤,本文通过命令实例相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-07-11
  • SqlServer 数据库 三大  范式

    本文将基于三大范式原则,结合具体的实例做简要分析,对SqlServer 数据库 三大 范式相关知识感兴趣的朋友一起看看吧...2020-07-11
  • sql server日志处理不当造成的隐患详解

    这篇文章主要给大家介绍了关于sql server日志处理不当造成的隐患的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用sql server具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-07-11
  • sqlserver添加sa用户和密码的实现

    这篇文章主要介绍了sqlserver添加sa用户和密码的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-05-07
  • PHP在Linux下连接MSSQLServer的配置方法简述(一、Sybase库)

    如果需要在Linux下访问Microsoft SQL Server或Sybase数据库,则推荐下列软件包。 SybaseCommon http://download.sybase.com/pub/ase1192_linux/sybase-common-11.9....2016-11-25
  • C#中Decimal类型截取保留N位小数并且不进行四舍五入操作

    这篇文章主要介绍了C#中Decimal类型截取保留N位小数并且不进行四舍五入操作,本文给出需求说明和实现代码,需要的朋友可以参考下...2020-06-25
  • c#操作sqlserver数据库的简单示例

    这篇文章主要介绍了c#操作sqlserver数据库的简单示例,需要的朋友可以参考下...2020-06-25
  • C# 启动 SQL Server 服务的实例

    下面小编就为大家分享一篇C# 启动 SQL Server 服务的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-06-25
  • sql server数据库中raiserror函数用法的详细介绍

    这篇文章主要介绍了sql server数据库中raiserror函数用法的详细介绍,raiserror用于抛出一个异常或错误,让这个错误可以被程序捕捉到。对此感兴趣的可以了解一下...2020-12-08
  • sqlserver中distinct的用法(不重复的记录)

    distinct这个关键字用来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的所有值。其原因是distinct只有用二重循环查询来解决,而这样对于一个数据量非常大的站来说,无疑是会直接影响到效率的。...2020-07-11
  • SqlServer 表单查询问题及解决方法

    这篇文章主要介绍了SqlServer 表单查询问题及解决方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下...2020-07-11
  • sqlserver 批量数据替换助手V1.0版发布

    前段时间网站被挂马,数据库表中很多文本字段都被加上了一段js脚本。修复完程序漏洞之后便开始着手清理这些被注入的数据,其间参考了一些网上的方法,大都是写一个存储过程进行一个表一个表逐一清理。...2021-09-22
  • c++读取sqlserver示例分享

    这篇文章主要介绍了c++读取sqlserver的示例,需要的朋友可以参考下...2020-04-25
  • sqlserver 普通用户运行错误解决方法补充

    本方法作为Windows2003服务器安装及设置教程——MSSQL安全篇一(将MS SQL SERVER运行于普通用户下)的补充,成功解决了不能将sqlserver运行在普通用户的权限下的问题。...2016-01-27
  • win98 PWS环境下连接读取远程SQLServer

    from: http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=4&txtCodeId=6518 Connect/Read Remote SQL server Using PWS in win 98 I had to t...2016-11-25