Ils sont en fait équivalents, mais ce sont des types indépendants, et non techniquement synonymes, comme ROWVERSION
et TIMESTAMP
- bien qu'ils aient été appelés synonymes dans la documentation à la fois . C’est une signification légèrement différente de synonyme (par exemple, ils ne peuvent être distingués que par leur nom, aucun n’est un alias pour l’autre). Ironique, non?
Ce que j’interprète à partir du libellé de MSDN est en réalité:
Ces types sont identiques, ils ont juste des noms différents.
Autre que les type_id
valeurs, tout est identique ici:
SELECT * FROM sys.types WHERE name IN (N'numeric', N'decimal');
Je ne connais absolument aucune différence de comportement entre les deux. Pour revenir à SQL Server 6.5, je les ai toujours traitées comme interchangeables à 100%.
pour DECIMAL (18,2) et NUMERIC (18,2)? Assigner l'un à l'autre est techniquement une "conversion"?
Seulement si vous le faites explicitement. Vous pouvez facilement le prouver en créant une table, puis en inspectant le plan de requête pour rechercher les requêtes qui effectuent des conversions explicites ou implicites. Voici un tableau simple:
CREATE TABLE [dbo].[NumDec]
(
[num] [numeric](18, 0) NULL,
[dec] [decimal](18, 0) NULL
);
Maintenant, lancez ces requêtes et capturez le 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
Comme indiqué dans SQL Sentry Plan Explorer *, le plan n’est pas vraiment intéressant:
Mais l'onglet Expressions est bien sûr:
Comme je l'ai mentionné ci-dessus, nous avons des conversions explicites où nous les avons demandées, mais pas de conversions explicites où nous aurions pu les attendre. Il semble que l’optimiseur les traite également comme interchangeables.
Allez-y et essayez ce test aussi (données et index).
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]);
Maintenant, lancez cette requête:
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;
Plan n'a aucune conversion (en fait, l'onglet Expressions est vide):
Même ceux-ci ne conduisent à aucune conversion inattendue. Bien sûr, cela se voit sur le RHS dans le prédicat, mais dans aucun cas, aucune conversion ne doit avoir lieu contre les données de colonne pour faciliter la recherche (et encore moins forcer une analyse).
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);
Personnellement, je préfère utiliser le terme DECIMAL
simplement parce qu'il est beaucoup plus précis et descriptif. BIT
est "numérique" aussi.
* Disclaimer: I work for SQL Sentry.