{"id":795,"date":"2011-09-16T23:03:00","date_gmt":"2011-09-16T23:03:00","guid":{"rendered":"http:\/\/mooredynasty.net\/?p=795"},"modified":"2014-12-18T23:03:50","modified_gmt":"2014-12-18T23:03:50","slug":"sql-server-datetime-debugging-gotcha","status":"publish","type":"post","link":"https:\/\/mooredynasty.net\/index.php\/2011\/09\/sql-server-datetime-debugging-gotcha\/","title":{"rendered":"SQL Server Date\/Time Debugging Gotcha"},"content":{"rendered":"<h4>Debugging SQL Server stored procedures is normally a straightforward operation.&#160; Even so, it\u2019s possible to be taken down the wrong path by the SQL Profiler and SQL Server Management Studio.<\/h4>\n<p>Assume a web page is receiving an exception calling a stored procedure that accepts a datetime field as a parameter.&#160; A natural thing to do to debug the scenario is to turn on the SQL Profiler, capture the SQL being executed, and analyze it.&#160; Doing so might yield a bit of SQL like the following:<\/p>\n<blockquote>\n<p>declare @p6 int<\/p>\n<p>set @p6=NULL<\/p>\n<p>exec sp_executesql N&#8217;EXEC @RETURN_VALUE = [dbo].[spSelectEmployeeData] @Role = @p0, @InputDate = @p1, @EmployeeNbr = @p2&#8242;,N&#8217;@p0 varchar(15),@p1 datetime,@p2 char(9),@RETURN_VALUE int output&#8217;,<\/p>\n<p>@p0=&#8217;EMPLOYEE&#8217;,@p1=&#8217;2010-09-15 17:18:00.9770000&#8242;,@p2=&#8217;123123123&#8242;,@RETURN_VALUE=@p6 output<\/p>\n<p>select @p6<\/p>\n<\/blockquote>\n<p>After considering this for a moment you might think, \u201cThat looks alright, why don\u2019t I run it and see what it does from SSMS, thus eliminating the web page and application layer from the call?\u201d<\/p>\n<p>Sadly running this SQL will yield an exception:<\/p>\n<blockquote>\n<p>Error converting data type varchar to datetime<\/p>\n<\/blockquote>\n<p>Resolving the exception is simple enough.&#160; Simply remove the trailing spaces from the milliseconds portion of the date parameter supplied to the stored procedure.&#160; Now everything works fine.<\/p>\n<p>The logical conclusion at this point is that the web application is passing an unacceptable value to the stored procedure.&#160; This thought makes sense because SQL datetime fields have 3 digits of precision when it comes to milliseconds, whereas the new datetime2 data type has 7.&#160; <\/p>\n<p>Furthermore, if you change the datetime parameter in the SQL above to a datetime2, the query works as expected.<\/p>\n<p>Now throw into the equation the fact that the web application has been running successfully for some years.&#160; The next logical leap is to question recent changes to ADO.NET or the SQL Server, particularly if the error is observed in proximity to \u201cPatch Tuesday\u201d.&#160; What\u2019s happened to my servers?!&#160; You may cry.<\/p>\n<p>Sadly, this is a red herring.&#160; The SQL Profiler displays datetime parameters with 7 digits worth of milliseconds regardless of what was sent to SQL Server by ADO.&#160; However, because datetime is the type of the parameter expected by the stored procedure, the wrapping SQL execution code does not use datetime2.&#160; This causes the conversion error which has nothing to do with the original problem.<\/p>\n<p>So why was the web page failing?&#160; An application code error that took 10 minutes to isolate and fix, once the distraction of SQL Profiler\u2019s improper formatting of the datetime parameter was removed from consideration.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Debugging SQL Server stored procedures is normally a straightforward operation.&#160; Even so, it\u2019s possible to be taken down the wrong path by the SQL Profiler and SQL Server Management Studio. Assume a web page is receiving an exception calling a stored procedure that accepts a datetime field as a parameter.&#160; &hellip; <\/p>\n","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15],"tags":[],"class_list":["post-795","post","type-post","status-publish","format-standard","hentry","category-development"],"_links":{"self":[{"href":"https:\/\/mooredynasty.net\/index.php\/wp-json\/wp\/v2\/posts\/795","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mooredynasty.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mooredynasty.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mooredynasty.net\/index.php\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/mooredynasty.net\/index.php\/wp-json\/wp\/v2\/comments?post=795"}],"version-history":[{"count":1,"href":"https:\/\/mooredynasty.net\/index.php\/wp-json\/wp\/v2\/posts\/795\/revisions"}],"predecessor-version":[{"id":796,"href":"https:\/\/mooredynasty.net\/index.php\/wp-json\/wp\/v2\/posts\/795\/revisions\/796"}],"wp:attachment":[{"href":"https:\/\/mooredynasty.net\/index.php\/wp-json\/wp\/v2\/media?parent=795"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mooredynasty.net\/index.php\/wp-json\/wp\/v2\/categories?post=795"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mooredynasty.net\/index.php\/wp-json\/wp\/v2\/tags?post=795"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}