Na verdade, são equivalentes, mas são tipos independentes e não são sinônimos tecnicamente , como ROWVERSION
e TIMESTAMP
- embora possam ter sido referidos como sinônimos na documentação ao mesmo tempo . Esse é um significado ligeiramente diferente de sinônimo (por exemplo, eles são indistinguíveis, exceto no nome, nenhum é um apelido para o outro). Irônico, certo?
O que eu interpreto da redação no MSDN é realmente:
Esses tipos são idênticos, eles apenas têm nomes diferentes.
Além dos type_id
valores, tudo aqui é idêntico:
SELECT * FROM sys.types WHERE name IN (N'numeric', N'decimal');
Não tenho absolutamente nenhum conhecimento de diferenças comportamentais entre os dois e, voltando ao SQL Server 6.5, sempre os tratamos como 100% intercambiáveis.
para DECIMAL (18,2) e NUMÉRICO (18,2)? Atribuir um ao outro é tecnicamente uma "conversão"?
Somente se você fizer isso explicitamente. Você pode provar isso facilmente criando uma tabela e depois inspecionando o plano de consulta para consultas que executam conversões explícitas ou - você pode esperar - implícitas. Aqui está uma tabela simples:
CREATE TABLE [dbo].[NumDec]
(
[num] [numeric](18, 0) NULL,
[dec] [decimal](18, 0) NULL
);
Agora execute essas consultas e capture o plano:
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
Conforme mostrado no SQL Sentry Plan Explorer *, o plano não é realmente interessante:
Mas a guia Expressões com certeza é:
Como comentei acima, temos conversões explícitas onde pedimos, mas não há conversões explícitas onde poderíamos tê-las esperado. Parece que o otimizador também os está tratando como intercambiáveis.
Vá em frente e tente este teste também (dados e índices).
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]);
Agora execute esta consulta:
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;
O plano não possui conversões (na verdade, a guia Expressões está vazia):
Mesmo estes não levam a conversões inesperadas. É claro que você o vê no RHS no predicado, mas em nenhum caso ocorreu nenhuma conversão nos dados da coluna para facilitar a busca (muito menos forçar uma varredura).
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);
Pessoalmente, prefiro usar o termo DECIMAL
apenas porque é muito mais preciso e descritivo. BIT
também é "numérico".
* Disclaimer: I work for SQL Sentry.