我知道 SQL Server 中的 NUMERIC 和 DECIMAL 数据类型的工作方式相同:创建它们的语法相同,可以存储在其中的值范围相同,等等。
但是,MSDN 文档将两者之间的关系描述为:
numeric 在功能上等同于十进制。
通常,当我看到限定词“功能等效”时,这意味着这两个东西并不完全相同,而是它们是两种不同的类型,从外面无法区分。
这个暗示是真的吗?NUMERIC 和 DECIMAL 之间是否存在恰好对外部观察者表现相同的差异?还是它们实际上是等价的,例如,NUMERIC 是否只是 DECIMAL 的旧同义词?
它们实际上是等价的,但它们是独立的类型,而不是技术上的同义词,例如ROWVERSIONand TIMESTAMP- 尽管它们可能曾经在文档中被称为同义词。这是同义词的稍微不同的含义(例如,除了名称之外,它们无法区分,没有一个是另一个的别名)。很讽刺,对吧?
ROWVERSION
TIMESTAMP
我从 MSDN 中的措辞解释的实际上是:
这些类型是相同的,只是名称不同。
除了type_id值之外,这里的一切都是相同的:
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也是“数字”。
DECIMAL
BIT
* Disclaimer: I work for SQL Sentry.