En realidad son equivalentes, pero son tipos independientes, y no técnicamente sinónimos, como ROWVERSION
y TIMESTAMP
, aunque pueden haber sido referidos como sinónimos en la documentación alguna vez . Ese es un significado ligeramente diferente del sinónimo (por ejemplo, no se pueden distinguir excepto en el nombre, ninguno es un alias para el otro). Irónico, ¿verdad?
Lo que interpreto de la redacción en MSDN es en realidad:
Estos tipos son idénticos, solo tienen nombres diferentes.
Aparte de los type_id
valores, todo aquí es idéntico:
SELECT * FROM sys.types WHERE name IN (N'numeric', N'decimal');
No tengo absolutamente ningún conocimiento de las diferencias de comportamiento entre los dos, y volviendo a SQL Server 6.5, siempre los he tratado como 100% intercambiables.
para DECIMAL (18,2) y NUMERIC (18,2)? ¿Asignar uno al otro es técnicamente una "conversión"?
Solo si lo haces explícitamente. Puede probar esto fácilmente creando una tabla y luego inspeccionando el plan de consultas para consultas que realizan conversiones explícitas o, como es de esperar, implícitas. Aquí hay una tabla simple:
CREATE TABLE [dbo].[NumDec]
(
[num] [numeric](18, 0) NULL,
[dec] [decimal](18, 0) NULL
);
Ahora ejecute estas consultas y capture el plan:
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
Como se muestra en SQL Sentry Plan Explorer *, el plan no es realmente interesante:
Pero la pestaña Expresiones seguro es:
Como comenté anteriormente, tenemos conversiones explícitas donde las solicitamos, pero no conversiones explícitas donde podríamos haberlas esperado. Parece que el optimizador también los trata como intercambiables.
Siga adelante y pruebe esta prueba también (datos 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]);
Ahora ejecute 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;
El plan no tiene conversiones (de hecho, la pestaña Expresiones está vacía):
Incluso estos no conducen a ninguna conversión inesperada. Por supuesto, lo ve en el RHS en el predicado, pero en ningún caso tuvo que ocurrir ninguna conversión contra los datos de la columna para facilitar la búsqueda (mucho menos forzar un escaneo).
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);
Personalmente, prefiero usar el término DECIMAL
solo porque es mucho más preciso y descriptivo. BIT
es "numérico" también.
* Disclaimer: I work for SQL Sentry.