它们实际上是等效的,但它们是独立的类型,在技术上不是同义词,就像ROWVERSION
和TIMESTAMP
-尽管它们可能在文档中一次被称为同义词。这与同义词的含义稍有不同(例如,除了名称上,它们是无法区分的,没有一个是另一个的别名)。具有讽刺意味,对吗?
我从MSDN中的措辞解释的实际上是:
这些类型是相同的,只是名称不同。
除了这些type_id
值,这里的所有内容都是相同的:
SELECT * FROM sys.types WHERE name IN (N'numeric', N'decimal');
我绝对不了解两者之间的任何行为差异,回到SQL Server 6.5,始终将它们视为100%可互换的。
用于DECIMAL(18,2)和NUMERIC(18,2)吗?从技术上讲,将一个分配给另一个是“转换”吗?
仅当您明确地这样做时。您可以通过创建一个表,然后检查查询计划中执行显式或隐式转换的查询来轻松证明这一点。这是一个简单的表:
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
如SQL Sentry Plan Explorer *中所示,该计划并不是很有趣:
但是“表达式”选项卡肯定是:
正如我在上面评论的那样,我们在要求的地方进行了明确的转换,但是在我们可能期望的地方没有进行明确的转换。似乎优化器也将它们视为可互换的。
继续尝试该测试(数据和索引)。
CREATE TABLE [dbo].[NumDec2]
(
[num] [numeric](18, 2) NULL,
[dec] [decimal](18, 2) NULL
);
INSERT dbo.NumDec2([num],[dec])
SELECT [object_id] + 0.12, [object_id] + 0.12
FROM sys.all_columns;
CREATE INDEX [ix_num] ON dbo.NumDec2([num]);
CREATE INDEX [ix_dec] ON dbo.NumDec2([dec]);
现在运行以下查询:
DECLARE @num NUMERIC(18,2) = -1291334356.88,
@dec NUMERIC(18,2) = -1291334356.88;
SELECT [dec] FROM dbo.NumDec2 WHERE [dec] = @num
UNION ALL
SELECT [num] FROM dbo.NumDec2 WHERE [num] = @dec;
计划没有转化(实际上“表达式”标签为空):
即使这些也不会导致任何意外的转换。当然,您可以在RHS中的谓词中看到它,但是在任何情况下都不必对列数据进行任何转换以方便查找(减少了强制扫描)。
SELECT [dec] FROM dbo.NumDec2 WHERE [dec] = CONVERT(DECIMAL(18,2), @num)
UNION ALL
SELECT [dec] FROM dbo.NumDec2 WHERE [dec] = CONVERT(DECIMAL(18,2), @dec)
UNION ALL
SELECT [num] FROM dbo.NumDec2 WHERE [num] = CONVERT(NUMERIC(18,2), @num)
UNION ALL
SELECT [num] FROM dbo.NumDec2 WHERE [num] = CONVERT(NUMERIC(18,2), @dec)
UNION ALL
SELECT [num] FROM dbo.NumDec2 WHERE [num] = CONVERT(DECIMAL(18,2), @num)
UNION ALL
SELECT [num] FROM dbo.NumDec2 WHERE [num] = CONVERT(DECIMAL(18,2), @dec)
UNION ALL
SELECT [dec] FROM dbo.NumDec2 WHERE [dec] = CONVERT(NUMERIC(18,2), @num)
UNION ALL
SELECT [dec] FROM dbo.NumDec2 WHERE [dec] = CONVERT(NUMERIC(18,2), @dec);
就我个人而言,我更喜欢使用该术语DECIMAL
,因为它更准确和更具描述性。BIT
也是“数字”。
* Disclaimer: I work for SQL Sentry.