Måske er du stødt på T-SQL-funktionerne PARSE()
, CAST()
og CONVERT()
, når du arbejder med SQL Server, og du har spekuleret på, hvad forskellen er. Alle tre funktioner ser ud til at gøre det samme, men der er subtile forskelle mellem dem.
I denne artikel har jeg til formål at skitsere de vigtigste forskelle mellem disse funktioner.
Sammenligning
Her er en tabel, der beskriver de vigtigste forskelle mellem CONVERT()
, CAST()
og PARSE()
-funktionerne i SQL Server:
CONVERT() | CAST() | PARSE() | ||
---|---|---|---|---|
Officiel definition | Konverterer et udtryk af én datatype til en anden. | Konverterer et udtryk af én datatype til en anden. | Returnerer resultatet af et udtryk, oversat til den ønskede datatype i SQL Server. | |
Accepteret værdi | Alle gyldige udtryk. | Alt gyldigt udtryk. | String. | |
Returneringsværdi | 2. argument, oversat til den ønskede datatype som angivet af det første argument. | 1ste argument, oversat til den ønskede datatype som angivet af det 2. argument. | 1ste argument, oversat til den ønskede datatype som angivet af det 2. argument. | |
Støttede konverteringer | Mellem to vilkårlige datatyper. | Mellem to vilkårlige datatyper. | Kun fra streng til dato/tids- og taltyper. | |
Accepterer stilargumentet? | Ja. | Nej. | Nej. | |
Accepterer argumentet culture? | Nej. | Nej. | Nej. | Ja. |
Kræver .NET Framework? | Nej. | Nej. | Nej. | Ja. |
Nogle andre punkter ud over ovenstående tabel:
- Microsoft-dokumentationen gør opmærksom på, at
PARSE()
ikke vil blive remoted (da det afhænger af tilstedeværelsen af CLR). Remoting af en funktion, der kræver CLR, vil medføre en fejl på fjernserveren. - Der er nogle værdier, som
PARSE()
kan håndtere, men somCAST()
ogCONVERT()
ikke kan håndtere (f.eks. strenge, der anvender visse datoformater). -
CAST()
er med i ANSI SQL-92-standarden. - Nogle hævder, at
CAST()
har bedre ydeevne end de to andre. - Der er et vist ydelsesoverhead ved parsing af strengværdier. Derfor vil
PARSE()
typisk køre langsommere end de to andre.
Nedenfor er der eksempler på situationer, hvor hver funktion vil være den bedst egnede.
Hvornår skal man bruge CAST()
Der kan argumenteres for at bruge CAST()
til ethvert scenarie, der ikke er nævnt nedenfor. Som nævnt har CAST()
været en del af ANSI SQL-standarden siden SQL-92, så den skulle være mere transportabel mellem forskellige DBMS’er (hvis det er et krav).
Der er også nogle, der hævder, at CAST()
har bedre ydeevne end de to andre (her er en interessant artikel, der sammenligner ydeevnen mellem alle tre funktioner).
Der er dog også gyldige grunde til, at du måske foretrækker (eller har brug for) at bruge CONVERT()
frem for CAST()
.
Når du skal bruge CONVERT()
Funktionen CONVERT()
kan være praktisk, når du skal bruge style
-argumentet til at angive, hvordan datoen skal formateres, når den konverteres mellem en dato og en streng. Her er nogle eksempler:
DECLARE @date datetime2 = '2018-06-07 02:35:52.8537677';SELECT CONVERT(nvarchar(30), @date, 100) AS '100', CONVERT(nvarchar(30), @date, 101) AS '101', CONVERT(nvarchar(30), @date, 102) AS '102', CONVERT(nvarchar(30), @date, 103) AS '103';
Resultat:
+---------------------+------------+------------+------------+| 100 | 101 | 102 | 103 ||---------------------+------------+------------+------------|| Jun 7 2018 2:35AM | 06/07/2018 | 2018.06.07 | 07/06/2018 |+---------------------+------------+------------+------------+
Du kan kun gøre dette med CONVERT()
, fordi:
-
CAST()
understøtter ikkestyle
-argumentet; og -
PARSE()
konverterer ikke fra en dato/tid til en strengværdi (den understøtter heller ikkestyle
-argumentet)
Hvornår skal man bruge PARSE()
Trods de forskellige ulemper ved denne funktion (ydeevne, afhængighed af .NET, begrænsede datatype-konverteringer), har den også nogle fordele, og der er nogle scenarier, hvor den kan være dit eneste valg. F.eks. når du leverer en dato, der indeholder ugedagsnavnet, f.eks. fredag den 20. juli 2018.
Når de andre returnerer en fejl
Her er eksempler, hvor PARSE()
er den eneste funktion af de tre, der kan konvertere værdien med succes uden at kaste en fejl.
I disse eksempler forsøger vi at konvertere forskellige strengværdier til en datatype for dato. De strengværdier, vi angiver, omfatter dog også ugedagsnavnet. Dette giver problemer for CAST()
og CONVERT()
, men PARSE()
har ingen problemer.
PARSE()
SELECT PARSE('Friday, 20 July 2018' AS date) AS 'Result 1', PARSE('Fri, 20 July 2018' AS date) AS 'Result 2', PARSE('Friday 20 July 2018' AS date) AS 'Result 3';
Resultat:
+------------+------------+------------+| Result 1 | Result 2 | Result 3 ||------------+------------+------------|| 2018-07-20 | 2018-07-20 | 2018-07-20 |+------------+------------+------------+
Så PARSE()
har ingen problemer med formatet af den dato, som vi leverer.
CONVERT()
SELECT CONVERT(date, 'Friday, 20 July 2018') AS 'Result 1', CONVERT(date, 'Fri, 20 July 2018') AS 'Result 2', CONVERT(date, 'Friday 20 July 2018') AS 'Result 3';
Resultat:
Conversion failed when converting date and/or time from character string.
Så CONVERT()
er ikke i stand til at konvertere strengen, når den er i et sådant format.
CAST()
SELECT CAST('Friday, 20 July 2018' AS date) AS 'Result 1', CAST('Fri, 20 July 2018' AS date)AS 'Result 2', CAST('Friday 20 July 2018' AS date) AS 'Result 3';
Resultat:
Conversion failed when converting date and/or time from character string.
Og CAST()
returnerer den samme fejl.
Så hvis du oplever, at du får fejl med de to andre funktioner, skal du prøve PARSE()
i stedet.
Specificering af kultur
Et andet scenarie, hvor du måske foretrækker at bruge funktionen PARSE()
, er ved specifikation af den kultur/det sprog, som strengen leveres i. PARSE()
har et valgfrit argument, der giver dig mulighed for at angive, hvilken kultur der skal bruges. Hvis det udelades, bruges sproget i den aktuelle session.
Eksempel på medtagelse af culture
-argumentet:
SELECT PARSE('07/01/2018' AS date USING 'en-US') AS 'Result 1', PARSE('07/01/2018' AS date USING 'de-DE') AS 'Result 2';
Resultat:
+------------+------------+| Result 1 | Result 2 ||------------+------------|| 2018-07-01 | 2018-01-07 |+------------+------------+
Et kulturalternativ
Trods fordelen ved at kunne angive kulturen med PARSE()
har du mulighed for at ændre sprogindstillingerne, hvilket betyder, at du kan opnå den samme effekt ved at bruge CAST()
eller CONVERT()
.
For eksempel vil du ved at bruge SET LANGUAGE us_english
før forespørgslen ændre de aktuelle sprogindstillinger til us_english. Selv om dette ikke giver dig mulighed for at angive forskellige kulturer i forespørgslen (som i ovenstående eksempel), påvirker det hele forespørgslen (og eventuelle efterfølgende forespørgsler).
Du kan også ændre indstillingerne for datoformat på samme måde. For eksempel SET DATEFORMAT mdy
.
Her er et eksempel på ændring af sprogindstillingen, inden du kører en forespørgsel med CAST()
og CONVERT()
:
Tysk:
SET LANGUAGE German;SELECT CONVERT(date, '07/01/2018') AS 'Convert';SELECT CAST('07/01/2018' AS date) AS 'Cast';
Resultat:
+------------+| Convert ||------------|| 2018-01-07 |+------------+Die Spracheneinstellung wurde in Deutsch geändert.+------------+| Cast ||------------|| 2018-01-07 |+------------+
us_english:
SET LANGUAGE us_english;SELECT CONVERT(date, '07/01/2018') AS 'Convert';SELECT CAST('07/01/2018' AS date) AS 'Cast';
Resultat:
+------------+| Convert ||------------|| 2018-07-01 |+------------+Changed language setting to us_english.+------------+| Cast ||------------|| 2018-07-01 |+------------+
Husk, at når du gør dette, ændrer du sprog-/datumsformatmiljøet for sessionen. Glem ikke at ændre det igen!