Considérez les deux façons suivantes pour convertir une chaîne varchar datetime en un champ de date:
SELECT convert(date, '2012-12-21 21:12:00', 20) -- Only date is needed
SELECT cast('2012-12-21 21:12:00' as date) -- Only date is needed
Les deux renvoient ce que j'attends: la date excluant l'heure, en tant que type de données date.
Ma question est la suivante: y a-t-il des avantages et des inconvénients à faire quoi que ce soit?
La réponse (anciennement) acceptée estétait incorrect car estétait un test mauvais et trompeur. Les deux requêtes comparées ne font pas la même chose en raison d'une simple faute de frappe qui fait qu'elles ne sont pas une comparaison de pommes à pommes. Le test de la réponse acceptée est injustement biaisé en faveur de l'opération CAST
. Le problème est que l'opération CONVERT
se fait avec convert(date, GETDATE()+num,20)
- une valeur à convertir qui change par ligne - tandis que l'opération CAST
se fait avec un simple cast(GETDATE() as date)
- une valeur à convertir qui est cohérente sur toutes les lignes et est remplacée dans le plan d'exécution en tant que constante. Et en fait, regarder le plan d'exécution XML montre même que l'opération réelle effectuée est CONVERT(date,getdate(),0)
!!
Dans la mesure où mes tests le montrent (après les avoir rendus égaux en utilisant cast(GETDATE()+num as date)
), les temps varient avec eux étant essentiellement les mêmes (ce qui est logique s'ils sont tous les deux réduits à être CONVERT
de toute façon) ou le CONVERT
gagnant:
SET STATISTICS IO, TIME ON;
;with t as (
select convert(date, GETDATE(),20) as fecha , 0 as num
union all
select convert(date, GETDATE()+num,20) as fecha, num+1 from t where num<1000000)
select max(fecha)
from t
option (maxrecursion 0);
SET STATISTICS IO, TIME OFF;
-- 4754-07-23
--Table 'Worktable'. Scan count 2, logical reads 6000008, physical reads 0, read-ahead reads 0
-- SQL Server Execution Times:
-- CPU time = 9031 ms, elapsed time = 9377 ms.
-- VS
SET STATISTICS IO, TIME ON;
;with t as (
select cast(GETDATE() as date) as fecha , 0 as num
union all
select cast(GETDATE() as date) as fecha, num+1 from t where num<1000000)
select max(fecha)
from t
option (maxrecursion 0);
SET STATISTICS IO, TIME OFF;
--2016-08-26
--Table 'Worktable'. Scan count 2, logical reads 6000008, physical reads 0, read-ahead reads 0
-- SQL Server Execution Times:
-- CPU time = 8969 ms, elapsed time = 9302 ms.
SET STATISTICS IO, TIME ON;
;with t as (
select cast(GETDATE() as date) as fecha , 0 as num
union all
select cast(GETDATE()+num as date) as fecha, num+1 from t where num<1000000)
select max(fecha)
from t
option (maxrecursion 0);
SET STATISTICS IO, TIME OFF;
-- 4754-07-23
--Table 'Worktable'. Scan count 2, logical reads 6000008, physical reads 0, read-ahead reads 0
-- SQL Server Execution Times:
-- CPU time = 9438 ms, elapsed time = 9878 ms.
La principale différence entre CAST et CONVERT est que CONVERT
permet de spécifier le "style". Le "style" permet non seulement de personnaliser la sortie lors de la conversion d'une non-chaîne en chaîne, mais permet également de spécifier le entrez le format lors de la conversion d'une chaîne en une non-chaîne:
SELECT CONVERT(DATE, '5/10/2016', 101); -- 101 = mm/dd/yyyy
-- 2016-05-10
SELECT CONVERT(DATE, '5/10/2016', 103); -- 103 = dd/mm/yyyy
-- 2016-10-05
Comparez maintenant cela fonctionnellement avec CAST
:
SELECT CAST('13/5/2016' AS DATE);
-- Msg 241, Level 16, State 1, Line 71
-- Conversion failed when converting date and/or time from character string.
SELECT CONVERT(DATE, '13/5/2016', 101); -- 101 = mm/dd/yyyy
-- Msg 241, Level 16, State 1, Line 76
-- Conversion failed when converting date and/or time from character string.
SELECT CONVERT(DATE, '13/5/2016', 103); -- 103 = dd/mm/yyyy
-- 2016-05-13
Une autre chose à mentionner à propos de CAST
: parce qu'il n'a pas le paramètre "style", le format de la chaîne de date passée est supposé être celui de la culture actuelle (une propriété de session). La culture actuelle est indiquée par le @@LANGID
et @@LANGUAGE
variables système. Cela signifie que l'instruction CAST
qui a échoué dans le test directement ci-dessus pourrait réussir pour une culture/langue différente. Les tests suivants montrent ce comportement et comment cette même chaîne de date fonctionne avec CAST
lorsque la langue actuelle est "français" (et fonctionnerait avec plusieurs autres, en fonction des valeurs de la colonne dateformat
dans sys.syslanguages
):
IF (@@LANGID <> 0) -- us_english
BEGIN
PRINT 'Changing LANGUAGE to English...';
SET LANGUAGE ENGLISH;
SELECT @@LANGUAGE AS [CurrentLanguage], @@LANGID AS [LangID];
END;
SELECT @@LANGUAGE, CAST('13/5/2016' AS DATE) AS [Test 1];
-- Msg 241, Level 16, State 1, Line 71
-- Conversion failed when converting date and/or time from character string.
GO
SELECT @@LANGUAGE, CONVERT(DATE, '13/5/2016', 103) AS [Test 2]; -- 103 = dd/mm/yyyy
-- us_english 2016-05-13
GO
IF (@@LANGID <> 2) -- Français
BEGIN
PRINT 'Changing LANGUAGE to French...';
SET LANGUAGE FRENCH;
SELECT @@LANGUAGE AS [CurrentLanguage], @@LANGID AS [LangID];
END;
SELECT @@LANGUAGE, CAST('13/5/2016' AS DATE) AS [Test 3];
-- 2016-05-13
GO
SELECT @@LANGUAGE, CONVERT(DATE, '13/5/2016', 103) AS [Test 4]; -- 103 = dd/mm/yyyy
-- Français 2016-05-13
GO
-- Reset current language, if necessary.
IF (@@LANGID <> @@DEFAULT_LANGID)
BEGIN
DECLARE @Language sysname;
SELECT @Language = sl.[alias]
FROM sys.syslanguages sl
WHERE sl.[langid] = @@DEFAULT_LANGID;
PRINT N'Changing LANGUAGE back to default: ' + @Language + N'...';
SET LANGUAGE @Language;
SELECT @@LANGUAGE AS [CurrentLanguage], @@LANGID AS [LangID];
END;
Je ne suis au courant d'aucune différence de "performances" entre les deux. Apparemment, "CONVERT" est spécifique au serveur SQL tandis que CAST est conforme à la norme ANSI. Je crois que CONVERT vous offre plus d'options. Vous pouvez voir d'autres avantages/inconvénients ici ( http://searchsqlserver.techtarget.com/tip/The-difference-between-CONVERT-and-CAST-in-SQL-Server )
Citations directes du lien ...
Étant donné que SQL Server fournit les deux fonctions, il peut y avoir une certaine confusion quant à la meilleure solution à utiliser et dans quelles circonstances.
CONVERT est spécifique à SQL Server et permet une plus grande flexibilité lors de la conversion entre les valeurs de date et d'heure, les nombres fractionnaires et les signifiants monétaires.
CAST est la norme plus ANSI des deux fonctions, ce qui signifie que bien qu'il soit plus portable (c'est-à-dire qu'une fonction qui utilise CAST peut être utilisée dans d'autres applications de base de données plus ou moins en l'état), elle est également moins puissante.
J'ai essayé cette comparaison stupide. Modifié, il y avait une faute de frappe que @srutzky a apportée. Les résultats sont proches.
;with t as (
select convert(date, GETDATE(),20) as fecha , 0 as num
union all
select convert(date, GETDATE()+num,20) as fecha, num+1 from t where num<1000000)
select max(fecha)
from t
option (maxrecursion 0);
-- VS
;with t as (
select cast(GETDATE() as date) as fecha , 0 as num
union all
select cast(GETDATE()+num as date) as fecha, num+1 from t where num<1000000)
select max(fecha)
from t
option (maxrecursion 0);
Résultats très cohérents: