Вони насправді еквівалентні, але вони є незалежними типами, а не технічно синонімами, як, 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.