NUMERIC
SQL 数据类型和之间有什么区别DECIMAL
?如果数据库以不同的方式处理这些,我想至少知道如何:
- SQL 服务器
- 甲骨文
- 分贝/2
- MySQL
- PostgreSQL
此外,数据库驱动程序如何解释这些类型有什么不同吗?
对于几乎所有目的,它们都是相同的。
曾经,不同的供应商对几乎相同的事物使用不同的名称 ( NUMERIC
/ DECIMAL
)。SQL-92 使它们相同,但有一个细微差别,可能是供应商特定的:
NUMERIC
必须与定义的一样精确——因此,如果您在小数点左侧定义 4 个小数位,在其右侧定义 4 个小数位,则 DB 必须始终存储 4 + 4 个小数位,不多也不少.
DECIMAL
如果这更容易实现,则可以自由允许更高的数字。这意味着数据库实际上可以存储比指定更多的数字(由于幕后存储有空间用于额外的数字)。这意味着数据库可能允许12345.0000
在上面的示例中存储 4 + 4 位小数,但1.00005
如果这样做可能会影响任何未来的计算,则仍然不允许存储。
大多数当前的数据库系统将DECIMAL
andNUMERIC
视为完美的同义词,或者视为具有完全相同行为的两种不同类型。如果类型被认为是完全不同的,您可能无法在DECIMAL
引用列的NUMERIC
列上定义外键约束,反之亦然。
They are synonyms, no difference at all.
At least on SQL Server in the ANSI SQL standards.
This SO answer shows some difference in ANSI but I suspect in implementation they are the same
Postgres: 没有区别
在表 8.1 中的文档描述中看起来相同,但没有解释为什么单独提到它,所以根据 Tom Lane的帖子
在 Postgres 中没有任何区别。有两种类型名称,因为 SQL 标准要求我们接受这两种名称。快速浏览一下标准,似乎唯一的区别是:
17)NUMERIC specifies the data type exact numeric, with the decimal precision and scale specified by the <precision> and <scale>. 18)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>.
即,对于 DECIMAL,实现允许在小数点左侧允许比请求更多的数字。Postgres 不行使这种自由,因此对我们来说这些类型之间没有区别。
regards, tom lane
还有一个页面较低的文档清楚地说明,
十进制和数字类型是等价的。这两种类型都是 SQL 标准的一部分。
并且在别名表 decimal [ (p, s) ]
中也提到了别名numeric [ (p, s) ]
它们实际上是等价的,但它们是独立的类型,而不是技术上的同义词,如 ROWVERSION 和 TIMESTAMP - 尽管它们可能曾经在文档中被称为同义词。这是同义词的稍微不同的含义(例如,除了名称之外,它们无法区分,没有一个是另一个的别名)。很讽刺,对吧?
我从 MSDN 中的措辞实际上是: 这些类型是相同的,只是名称不同。
除了 type_id 值之外,这里的所有内容都是相同的:
SELECT * FROM sys.types WHERE name IN (N'numeric', N'decimal');
我完全不知道两者之间的任何行为差异,并且回到 SQL Server 6.5,一直将它们视为 100% 可互换。
for DECIMAL(18,2) and NUMERIC(18,2)? Assigning one to the other is technically a "conversion"?
仅当您明确这样做时。您可以通过创建一个表然后检查查询计划以查找执行显式或(您可能期望的)隐式转换的查询来轻松证明这一点。这是一个简单的表格:
CREATE TABLE [dbo].[NumDec]
(
[num] [numeric](18, 0) NULL,
[dec] [decimal](18, 0) NULL
);
现在运行这些查询并捕获计划:
DECLARE @num NUMERIC(18,0);
DECLARE @dec DECIMAL(18,0);
SELECT
CONVERT(DECIMAL(18,0), [num]), -- conversion
CONVERT(NUMERIC(18,0), [dec]) -- conversion
FROM dbo.NumDec
UNION ALL SELECT [num],[dec]
FROM dbo.NumDec WHERE [num] = @dec -- no conversion
UNION ALL SELECT [num],[dec]
FROM dbo.NumDec WHERE [dec] = @num; -- no conversion
我们在我们要求的地方有明确的转换,但在我们可能期望的地方没有明确的转换。似乎优化器也将它们视为可互换的。
就个人而言,我更喜欢使用 DECIMAL 一词,因为它更准确且更具描述性。BIT 也是“数字”的。