PARSE vs CAST and CONVERT
T-SQL often provides multiple ways to “skin a cat”1 as they say. In this post, we’ll take a look at two “interesting” ways to convert dates and times from character-based columns into a column using the preferred datetime
data-type.
PARSE
provides a mechanism to convert a wide variety of character based dates into a datetime data type. From the Docs:
Returns the result of an expression, translated to the requested data type in SQL Server.
Use PARSE only for converting from string to date/time and number types. For general type conversions, continue to use CAST or CONVERT. Keep in mind that there is a certain performance overhead in parsing the string value.
You might use PARSE to convert the following string into a date:
December 21, 1989 6:00 PM
The code you might use:
1 |
SELECT PARSE(N'December 21, 1989 6:00 PM' AS datetime USING 'en-GB'); |
Output looks like:
1989-12-21 18:00:00.000
Looks great. Ok, so now you’ve got that working, you’ll want to convert a table with a large number of rows that contain character-based dates into a datetime
column. You might use:
1 2 3 |
UPDATE t SET t.DateTimeColumn = PARSE(t.CharDateTime AS datetime USING 'en-GB') FROM dbo.MyTable t; |
That’ll work, but it’ll take a long time if you have a lot of rows. PARSE is sloooooow. Let’s compare the statement syntax to CAST
or CONVERT
. Personally, I prefer CONVERT
, even though it’s, gah, 3 characters longer to type.
1 2 |
SET LANGUAGE 'British'; SELECT CONVERT(datetime, N'December 21, 1989 6:00 PM'); |
That’s not that much harder. Output is identical to the PARSE
output from above, so I’ll not repeat it here.
So, lets compare how much time each variant takes. First, we’ll setup a couple of tables; one containing source data with dates stored in a varchar column, one for the output from PARSE
and one for the output from CONVERT
. The source table will contain 10,000 rows. 10,000 rows is not a lot, but it’ll suffice for this test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
DROP TABLE IF EXISTS dbo.ParseTest; DROP TABLE IF EXISTS dbo.ParseTestOutput1; DROP TABLE IF EXISTS dbo.ParseTestOutput2; GO CREATE TABLE dbo.ParseTest ( d varchar(23) NOT NULL ); INSERT INTO dbo.ParseTest(d) SELECT TOP(10000) DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1, '2019-08-20 00:00:00') FROM sys.syscolumns sc1 CROSS JOIN sys.syscolumns sc2; CREATE TABLE dbo.ParseTestOutput1 ( d datetime NOT NULL ); CREATE TABLE dbo.ParseTestOutput2 ( d datetime NOT NULL ); SELECT * FROM dbo.ParseTest; GO |
The last SELECT
ensures the data is in the buffer cache, which will help us get an apples-to-apples comparison of the time required to do the conversions.
Next, we’ll turn on statistics for I/O and time, then convert the data using PARSE and CONVERT:
1 2 3 4 5 6 7 8 9 10 11 |
SET STATISTICS IO, TIME ON; GO INSERT INTO dbo.ParseTestOutput1 (d) SELECT PARSE(pt.d AS datetime USING 'en-US') FROM dbo.ParseTest pt; GO INSERT INTO dbo.ParseTestOutput2 (d) SELECT CONVERT(datetime, pt.d) FROM dbo.ParseTest pt; |
The output looks like:
As you can see, the first test, using PARSE
, took over 2 seconds to convert 10,000 rows. The second test, using CONVERT
, took only 71 miliseconds, or 28.5 times faster.
The moral of this story? If you’re converting well-formed dates and times from character-based columns into datetime-based columns, and you care about speed, use CONVERT
(or CAST
, it’s the same thing). For a performance comparison of CAST vs CONVERT, see this post.
I hope you enjoyed this post, and would love it if you checked out the rest of our posts on SQL Server Performance.
1 – Don’t worry, no cats were harmed during the making of this post. It’s just a saying!
Does CAST allow you to specify style?
No,
CAST
does not provide a style option. I groupCAST
andCONVERT
together here because they are much more commonly used thanPARSE
, and the performance of both commands are much better thanPARSE
.[…] Hannah Vernon gives us three ways to change data types: […]