<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Damir's Corner - Development|SQL</title>
    <link>http://www.damirscorner.com/</link>
    <description>Notes from Daily Encounters with Technology</description>
    <language>en-us</language>
    <copyright>Damir Arh, M. Sc.</copyright>
    <lastBuildDate>Mon, 26 Dec 2011 18:28:18 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.9074.18820</generator>
    <managingEditor>damir.arh@gmail.com</managingEditor>
    <webMaster>damir.arh@gmail.com</webMaster>
    <item>
      <trackback:ping>http://www.damirscorner.com/Trackback.aspx?guid=10aa6db7-05e9-46be-9ab7-b661d0f36052</trackback:ping>
      <pingback:server>http://www.damirscorner.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.damirscorner.com/PermaLink,guid,10aa6db7-05e9-46be-9ab7-b661d0f36052.aspx</pingback:target>
      <dc:creator>Damir Arh</dc:creator>
      <wfw:comment>http://www.damirscorner.com/CommentView,guid,10aa6db7-05e9-46be-9ab7-b661d0f36052.aspx</wfw:comment>
      <wfw:commentRss>http://www.damirscorner.com/SyndicationService.asmx/GetEntryCommentsRss?guid=10aa6db7-05e9-46be-9ab7-b661d0f36052</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
DateTime can be a tricky data type to deal with. Not only is there daylight saving
time and different time zones to keep in mind but also the range and precision can
vary in different systems. You are probably already aware of some differences between
.NET framework’s <a href="http://msdn.microsoft.com/en-us/library/system.datetime.aspx">DateTime</a> structure
in Transact-SQL’s <a href="http://technet.microsoft.com/en-us/library/ms187819.aspx">datetime</a> data
type.
</p>
        <p>
Most notable is certainly a different minimum value that can be expressed:
</p>
        <ul>
          <li>
In .NET framework all values between January 1st 1 and December 31st 9999 are supported. 
</li>
          <li>
In Transact-SQL only values between January 1st 1753 and December 31st 9999 are supported.</li>
        </ul>
        <p>
This usually shouldn’t be a problem unless you are working with historic data. Setting
proper minimum value in the user interface is not be a bad idea nevertheless.
</p>
        <p>
You might not be aware of the difference in precision between these two data types,
though. In some edge cases this can cause strange and unpredictable behavior. Let’s
take a look at the following example (based on an issue that had me mystified for
some time):
</p>
        <pre class="brush: csharp;">using (var context = new TestEntities())
{
    var task = context.Tasks.Single(t =&gt; t.Id == taskId);
    task.CompletedAt = DateTime.Now;
    timestamp = task.CompletedAt.Value;
    context.SaveChanges();
}

using (var context = new TestEntities())
{
    var task = context.Tasks.Single(t =&gt; t.Id == taskId);
    Assert.GreaterOrEqual(timestamp, task.CompletedAt);
}

</pre>
        <p>
The assertion in the above code will occasionally fail with a message similar to this
one:
</p>
        <pre class="brush: plain;">SampleTest has failed:
  Expected: greater than or equal to 2011-12-26 19:04:28.313
  But was:  2011-12-26 19:04:28.312</pre>
        <p>
If you’re not familiar with entity framework, here’s what’s going on:
</p>
        <ul>
          <li>
In the first code block a DateTime value is stored to the database. 
</li>
          <li>
In the second code block that same value is reloaded from the database. 
</li>
          <li>
The value from the database is compared with the one stored in a local variable the
whole time.</li>
        </ul>
        <p>
The strange behavior is caused by the fact that milliseconds get rounded in the database:
to increments of .000, .003, or .007 seconds, as it is stated in the documentation.
The DateTime value can therefore be different when reloaded from the database, hence
the occasional failed assertion. While the problem might be fairly obvious in the
simplified example above, it can be much more difficult to pinpoint in a larger chunk
of code where there could be other reasons for the values to differ. Even more so
if you’re not even aware of the rounding.
</p>
        <p>
Knowing this might save you a couple of hours once.
</p>
        <img width="0" height="0" src="http://www.damirscorner.com/aggbug.ashx?id=10aa6db7-05e9-46be-9ab7-b661d0f36052" />
      </body>
      <title>DateTime Value Might Change When Saved to Database</title>
      <guid isPermaLink="false">http://www.damirscorner.com/PermaLink,guid,10aa6db7-05e9-46be-9ab7-b661d0f36052.aspx</guid>
      <link>http://www.damirscorner.com/DateTimeValueMightChangeWhenSavedToDatabase.aspx</link>
      <pubDate>Mon, 26 Dec 2011 18:28:18 GMT</pubDate>
      <description>&lt;p&gt;
DateTime can be a tricky data type to deal with. Not only is there daylight saving
time and different time zones to keep in mind but also the range and precision can
vary in different systems. You are probably already aware of some differences between
.NET framework’s &lt;a href="http://msdn.microsoft.com/en-us/library/system.datetime.aspx"&gt;DateTime&lt;/a&gt; structure
in Transact-SQL’s &lt;a href="http://technet.microsoft.com/en-us/library/ms187819.aspx"&gt;datetime&lt;/a&gt; data
type.
&lt;/p&gt;
&lt;p&gt;
Most notable is certainly a different minimum value that can be expressed:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
In .NET framework all values between January 1st 1 and December 31st 9999 are supported. 
&lt;li&gt;
In Transact-SQL only values between January 1st 1753 and December 31st 9999 are supported.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
This usually shouldn’t be a problem unless you are working with historic data. Setting
proper minimum value in the user interface is not be a bad idea nevertheless.
&lt;/p&gt;
&lt;p&gt;
You might not be aware of the difference in precision between these two data types,
though. In some edge cases this can cause strange and unpredictable behavior. Let’s
take a look at the following example (based on an issue that had me mystified for
some time):
&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;using (var context = new TestEntities())
{
    var task = context.Tasks.Single(t =&amp;gt; t.Id == taskId);
    task.CompletedAt = DateTime.Now;
    timestamp = task.CompletedAt.Value;
    context.SaveChanges();
}

using (var context = new TestEntities())
{
    var task = context.Tasks.Single(t =&amp;gt; t.Id == taskId);
    Assert.GreaterOrEqual(timestamp, task.CompletedAt);
}

&lt;/pre&gt;
&lt;p&gt;
The assertion in the above code will occasionally fail with a message similar to this
one:
&lt;/p&gt;
&lt;pre class="brush: plain;"&gt;SampleTest has failed:
  Expected: greater than or equal to 2011-12-26 19:04:28.313
  But was:  2011-12-26 19:04:28.312&lt;/pre&gt;
&lt;p&gt;
If you’re not familiar with entity framework, here’s what’s going on:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
In the first code block a DateTime value is stored to the database. 
&lt;li&gt;
In the second code block that same value is reloaded from the database. 
&lt;li&gt;
The value from the database is compared with the one stored in a local variable the
whole time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The strange behavior is caused by the fact that milliseconds get rounded in the database:
to increments of .000, .003, or .007 seconds, as it is stated in the documentation.
The DateTime value can therefore be different when reloaded from the database, hence
the occasional failed assertion. While the problem might be fairly obvious in the
simplified example above, it can be much more difficult to pinpoint in a larger chunk
of code where there could be other reasons for the values to differ. Even more so
if you’re not even aware of the rounding.
&lt;/p&gt;
&lt;p&gt;
Knowing this might save you a couple of hours once.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.damirscorner.com/aggbug.ashx?id=10aa6db7-05e9-46be-9ab7-b661d0f36052" /&gt;</description>
      <comments>http://www.damirscorner.com/CommentView,guid,10aa6db7-05e9-46be-9ab7-b661d0f36052.aspx</comments>
      <category>Development</category>
      <category>Development/.NET</category>
      <category>Development/SQL</category>
    </item>
    <item>
      <trackback:ping>http://www.damirscorner.com/Trackback.aspx?guid=f319cef5-7d48-49b0-bbe2-f411dddc6157</trackback:ping>
      <pingback:server>http://www.damirscorner.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.damirscorner.com/PermaLink,guid,f319cef5-7d48-49b0-bbe2-f411dddc6157.aspx</pingback:target>
      <dc:creator>Damir Arh</dc:creator>
      <wfw:comment>http://www.damirscorner.com/CommentView,guid,f319cef5-7d48-49b0-bbe2-f411dddc6157.aspx</wfw:comment>
      <wfw:commentRss>http://www.damirscorner.com/SyndicationService.asmx/GetEntryCommentsRss?guid=f319cef5-7d48-49b0-bbe2-f411dddc6157</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In a technical document I was working on today I hade to include some details about
database table definitions, including the column names, data types, primary and foreign
key information, and column descriptions stored in MS_Description extended property.
Using <a href="http://msdn.microsoft.com/en-us/library/ms186778.aspx">information
schema views</a> and the <a href="http://msdn.microsoft.com/en-us/library/ms179853.aspx">fn_listextendedproperty</a> function
I wrote a table valued function which returns information about all the columns in
the given table. I’m posting it here in case someone else finds it useful.
</p>
        <pre class="brush: sql;">CREATE FUNCTION [dbo].[GetColumnDetails] 
(    
    @tableName sysname
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT
        ColumnName = C.COLUMN_NAME, 
        DataType = UPPER(C.DATA_TYPE) + CASE
                WHEN C.CHARACTER_MAXIMUM_LENGTH = -1 THEN '(MAX)'
                WHEN C.CHARACTER_MAXIMUM_LENGTH IS NOT NULL THEN
                    '(' + CONVERT(nvarchar(10), C.CHARACTER_MAXIMUM_LENGTH) + ')'
                WHEN C.DATA_TYPE IN ('decimal', 'numeric') THEN
                    '(' + CONVERT(nvarchar(2), C.NUMERIC_PRECISION) + '; '    
                    + CONVERT(nvarchar(2), C.NUMERIC_SCALE) + ')'
                ELSE ''
            END
            + ', ' + CASE C.IS_NULLABLE 
                WHEN 'NO' THEN 'NOT NULL'
                ELSE 'NULL'
            END
            + CASE
                WHEN PK.CONSTRAINT_NAME IS NOT NULL THEN ', PK'
                ELSE ''
            END
            + CASE
                WHEN FK.CONSTRAINT_NAME IS NOT NULL THEN ', FK'
                ELSE ''
            END,
        Description = D.value
    FROM INFORMATION_SCHEMA.COLUMNS C
        LEFT OUTER JOIN
            (SELECT KCU.TABLE_NAME, KCU.COLUMN_NAME, KCU.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC
                INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU 
                ON TC.CONSTRAINT_NAME = KCU.CONSTRAINT_NAME AND TC.CONSTRAINT_TYPE = 'FOREIGN KEY') AS FK
            ON C.TABLE_NAME = FK.TABLE_NAME AND C.COLUMN_NAME = FK.COLUMN_NAME
        LEFT OUTER JOIN
            (SELECT KCU.TABLE_NAME, KCU.COLUMN_NAME, KCU.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC
                INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU 
                ON TC.CONSTRAINT_NAME = KCU.CONSTRAINT_NAME AND TC.CONSTRAINT_TYPE = 'PRIMARY KEY') AS PK
            ON C.TABLE_NAME = PK.TABLE_NAME AND C.COLUMN_NAME = PK.COLUMN_NAME
        LEFT OUTER JOIN
            fn_listextendedproperty('MS_Description', 'schema', 'dbo', 
                'table', @tableName, 'column', default) AS D 
            ON D.objname COLLATE database_default = C.COLUMN_NAME COLLATE database_default
    WHERE C.TABLE_NAME = @tableName
)
</pre>
        <img width="0" height="0" src="http://www.damirscorner.com/aggbug.ashx?id=f319cef5-7d48-49b0-bbe2-f411dddc6157" />
      </body>
      <title>T-SQL Function to Get Column Details from Database</title>
      <guid isPermaLink="false">http://www.damirscorner.com/PermaLink,guid,f319cef5-7d48-49b0-bbe2-f411dddc6157.aspx</guid>
      <link>http://www.damirscorner.com/TSQLFunctionToGetColumnDetailsFromDatabase.aspx</link>
      <pubDate>Fri, 10 Sep 2010 20:21:02 GMT</pubDate>
      <description>&lt;p&gt;
In a technical document I was working on today I hade to include some details about
database table definitions, including the column names, data types, primary and foreign
key information, and column descriptions stored in MS_Description extended property.
Using &lt;a href="http://msdn.microsoft.com/en-us/library/ms186778.aspx"&gt;information
schema views&lt;/a&gt; and the &lt;a href="http://msdn.microsoft.com/en-us/library/ms179853.aspx"&gt;fn_listextendedproperty&lt;/a&gt; function
I wrote a table valued function which returns information about all the columns in
the given table. I’m posting it here in case someone else finds it useful.
&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;CREATE FUNCTION [dbo].[GetColumnDetails] 
(    
    @tableName sysname
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT
        ColumnName = C.COLUMN_NAME, 
        DataType = UPPER(C.DATA_TYPE) + CASE
                WHEN C.CHARACTER_MAXIMUM_LENGTH = -1 THEN '(MAX)'
                WHEN C.CHARACTER_MAXIMUM_LENGTH IS NOT NULL THEN
                    '(' + CONVERT(nvarchar(10), C.CHARACTER_MAXIMUM_LENGTH) + ')'
                WHEN C.DATA_TYPE IN ('decimal', 'numeric') THEN
                    '(' + CONVERT(nvarchar(2), C.NUMERIC_PRECISION) + '; '    
                    + CONVERT(nvarchar(2), C.NUMERIC_SCALE) + ')'
                ELSE ''
            END
            + ', ' + CASE C.IS_NULLABLE 
                WHEN 'NO' THEN 'NOT NULL'
                ELSE 'NULL'
            END
            + CASE
                WHEN PK.CONSTRAINT_NAME IS NOT NULL THEN ', PK'
                ELSE ''
            END
            + CASE
                WHEN FK.CONSTRAINT_NAME IS NOT NULL THEN ', FK'
                ELSE ''
            END,
        Description = D.value
    FROM INFORMATION_SCHEMA.COLUMNS C
        LEFT OUTER JOIN
            (SELECT KCU.TABLE_NAME, KCU.COLUMN_NAME, KCU.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC
                INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU 
                ON TC.CONSTRAINT_NAME = KCU.CONSTRAINT_NAME AND TC.CONSTRAINT_TYPE = 'FOREIGN KEY') AS FK
            ON C.TABLE_NAME = FK.TABLE_NAME AND C.COLUMN_NAME = FK.COLUMN_NAME
        LEFT OUTER JOIN
            (SELECT KCU.TABLE_NAME, KCU.COLUMN_NAME, KCU.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC
                INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU 
                ON TC.CONSTRAINT_NAME = KCU.CONSTRAINT_NAME AND TC.CONSTRAINT_TYPE = 'PRIMARY KEY') AS PK
            ON C.TABLE_NAME = PK.TABLE_NAME AND C.COLUMN_NAME = PK.COLUMN_NAME
        LEFT OUTER JOIN
            fn_listextendedproperty('MS_Description', 'schema', 'dbo', 
                'table', @tableName, 'column', default) AS D 
            ON D.objname COLLATE database_default = C.COLUMN_NAME COLLATE database_default
    WHERE C.TABLE_NAME = @tableName
)
&lt;/pre&gt;&lt;img width="0" height="0" src="http://www.damirscorner.com/aggbug.ashx?id=f319cef5-7d48-49b0-bbe2-f411dddc6157" /&gt;</description>
      <comments>http://www.damirscorner.com/CommentView,guid,f319cef5-7d48-49b0-bbe2-f411dddc6157.aspx</comments>
      <category>Development</category>
      <category>Development/SQL</category>
    </item>
    <item>
      <trackback:ping>http://www.damirscorner.com/Trackback.aspx?guid=4dae342f-0fd4-4ef6-83db-d09cda3f5f18</trackback:ping>
      <pingback:server>http://www.damirscorner.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.damirscorner.com/PermaLink,guid,4dae342f-0fd4-4ef6-83db-d09cda3f5f18.aspx</pingback:target>
      <dc:creator>Damir Arh</dc:creator>
      <wfw:comment>http://www.damirscorner.com/CommentView,guid,4dae342f-0fd4-4ef6-83db-d09cda3f5f18.aspx</wfw:comment>
      <wfw:commentRss>http://www.damirscorner.com/SyndicationService.asmx/GetEntryCommentsRss?guid=4dae342f-0fd4-4ef6-83db-d09cda3f5f18</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
One would have thought this to be a well known fact but since one of our developers
stumbled upon it yesterday I thought it might be useful to someone else.
</p>
        <p>
As soon as a pooled connection with enabled application role gets reused an exception
gets thrown and its description is not really helpful if you’re not aware of the problem: <font face="Courier New">General
Network Error</font>. This happens because the security context of the connection
doesn’t get properly reset when it is closed. To work around the problem you can either
avoid using application roles or disable connection pooling (by adding <font face="Courier New">Pooling=False</font> to
the connection string). You can find more details <a href="http://support.microsoft.com/kb/229564">in
this knowledge base article</a>.
</p>
        <p>
It might be worth mentioning that the above is completely accurate only for SQL Server
2000. SQL Server 2005 comes with a new stored procedure <a href="http://msdn2.microsoft.com/en-us/library/ms365415.aspx"><font face="Courier New">sp_unsetapprole</font></a> which
can be used to reset the security context. I haven’t tried it but by calling it before
closing the connection you should be able to make application roles work together
with connection pooling.
</p>
        <img width="0" height="0" src="http://www.damirscorner.com/aggbug.ashx?id=4dae342f-0fd4-4ef6-83db-d09cda3f5f18" />
      </body>
      <title>Application roles and connection pooling</title>
      <guid isPermaLink="false">http://www.damirscorner.com/PermaLink,guid,4dae342f-0fd4-4ef6-83db-d09cda3f5f18.aspx</guid>
      <link>http://www.damirscorner.com/ApplicationRolesAndConnectionPooling.aspx</link>
      <pubDate>Fri, 20 Oct 2006 14:09:17 GMT</pubDate>
      <description>&lt;p&gt;
One would have thought this to be a well known fact but since one of our developers
stumbled upon it yesterday I thought it might be useful to someone else.
&lt;/p&gt;
&lt;p&gt;
As soon as a pooled connection with enabled application role gets reused an exception
gets thrown and its description is not really helpful if you’re not aware of the problem: &lt;font face="Courier New"&gt;General
Network Error&lt;/font&gt;. This happens because the security context of the connection
doesn’t get properly reset when it is closed. To work around the problem you can either
avoid using application roles or disable connection pooling (by adding &lt;font face="Courier New"&gt;Pooling=False&lt;/font&gt; to
the connection string). You can find more details &lt;a href="http://support.microsoft.com/kb/229564"&gt;in
this knowledge base article&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
It might be worth mentioning that the above is completely accurate only for SQL Server
2000. SQL Server 2005 comes with a new stored procedure &lt;a href="http://msdn2.microsoft.com/en-us/library/ms365415.aspx"&gt;&lt;font face="Courier New"&gt;sp_unsetapprole&lt;/font&gt;&lt;/a&gt; which
can be used to reset the security context. I haven’t tried it but by calling it before
closing the connection you should be able to make application roles work together
with connection pooling.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.damirscorner.com/aggbug.ashx?id=4dae342f-0fd4-4ef6-83db-d09cda3f5f18" /&gt;</description>
      <comments>http://www.damirscorner.com/CommentView,guid,4dae342f-0fd4-4ef6-83db-d09cda3f5f18.aspx</comments>
      <category>Development</category>
      <category>Development/.NET</category>
      <category>Development/SQL</category>
    </item>
    <item>
      <trackback:ping>http://www.damirscorner.com/Trackback.aspx?guid=41319b50-89e8-477e-827e-e518d6a28c47</trackback:ping>
      <pingback:server>http://www.damirscorner.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.damirscorner.com/PermaLink,guid,41319b50-89e8-477e-827e-e518d6a28c47.aspx</pingback:target>
      <dc:creator>Damir Arh</dc:creator>
      <wfw:comment>http://www.damirscorner.com/CommentView,guid,41319b50-89e8-477e-827e-e518d6a28c47.aspx</wfw:comment>
      <wfw:commentRss>http://www.damirscorner.com/SyndicationService.asmx/GetEntryCommentsRss?guid=41319b50-89e8-477e-827e-e518d6a28c47</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Today I’ve been evaluating database designs made by this year’s candidates for work
at our company. One of the issues I’ve been encountering all the time was the handling
of date and time values. The SQL Server’s common data type <font face="Courier New">datetime</font> for
both values has been the source of quite some confusion, especially since the values
required to be separate at some occasions and joined at others.
</p>
        <p>
I suppose the decision on whether to store them separate or joined depends on how
the values are going to be used. In most cases the extra storage space required by
using separate columns for both values isn’t worth it but in some usage scenarios
the resulting reduced query complexity and improved indexing usage can justify it.
</p>
        <p>
Either way sooner or later the need for separating or joining the date and time parts
will arise. The following query demonstrates both operations in what I believe is
the most efficient way:
</p>
        <p>
          <font face="Courier New">SELECT<br />
   dateOnly = CONVERT(datetime, FLOOR(CONVERT(float, dateTimeColumn))),<br />
   timeOnly = dateTimeColumn - CONVERT(datetime, FLOOR(CONVERT(float,
dateTimeColumn))),<br />
   dateAndTime = dateOnlyColumn + timeOnlyColumn <br />
FROM DateTable</font>
        </p>
        <img width="0" height="0" src="http://www.damirscorner.com/aggbug.ashx?id=41319b50-89e8-477e-827e-e518d6a28c47" />
      </body>
      <title>Splitting and joining date and time values</title>
      <guid isPermaLink="false">http://www.damirscorner.com/PermaLink,guid,41319b50-89e8-477e-827e-e518d6a28c47.aspx</guid>
      <link>http://www.damirscorner.com/SplittingAndJoiningDateAndTimeValues.aspx</link>
      <pubDate>Tue, 18 Apr 2006 21:38:07 GMT</pubDate>
      <description>&lt;p&gt;
Today I’ve been evaluating database designs made by this year’s candidates for work
at our company. One of the issues I’ve been encountering all the time was the handling
of date and time values. The SQL Server’s common data type &lt;font face="Courier New"&gt;datetime&lt;/font&gt; for
both values has been the source of quite some confusion, especially since the values
required to be separate at some occasions and joined at others.
&lt;/p&gt;
&lt;p&gt;
I suppose the decision on whether to store them separate or joined depends on how
the values are going to be used. In most cases the extra storage space required by
using separate columns for both values isn’t worth it but in some usage scenarios
the resulting reduced query complexity and improved indexing usage can justify it.
&lt;/p&gt;
&lt;p&gt;
Either way sooner or later the need for separating or joining the date and time parts
will arise. The following query demonstrates both operations in what I believe is
the most efficient way:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;SELECT&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;dateOnly = CONVERT(datetime, FLOOR(CONVERT(float, dateTimeColumn))),&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;timeOnly = dateTimeColumn - CONVERT(datetime, FLOOR(CONVERT(float,
dateTimeColumn))),&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;dateAndTime = dateOnlyColumn + timeOnlyColumn&amp;nbsp;&lt;br&gt;
FROM DateTable&lt;/font&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.damirscorner.com/aggbug.ashx?id=41319b50-89e8-477e-827e-e518d6a28c47" /&gt;</description>
      <comments>http://www.damirscorner.com/CommentView,guid,41319b50-89e8-477e-827e-e518d6a28c47.aspx</comments>
      <category>Development</category>
      <category>Development/SQL</category>
    </item>
    <item>
      <trackback:ping>http://www.damirscorner.com/Trackback.aspx?guid=f8225ed1-3047-44d7-a9a2-c64badbe5d91</trackback:ping>
      <pingback:server>http://www.damirscorner.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.damirscorner.com/PermaLink,guid,f8225ed1-3047-44d7-a9a2-c64badbe5d91.aspx</pingback:target>
      <dc:creator>Damir Arh</dc:creator>
      <wfw:comment>http://www.damirscorner.com/CommentView,guid,f8225ed1-3047-44d7-a9a2-c64badbe5d91.aspx</wfw:comment>
      <wfw:commentRss>http://www.damirscorner.com/SyndicationService.asmx/GetEntryCommentsRss?guid=f8225ed1-3047-44d7-a9a2-c64badbe5d91</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The following query is a good starting point if you want to export the SQL Server
Agent job history to a file and you’re still using Enterprise Manager from SQL Server
2000. In SQL Server Management Studio from SQL Server 2005 there’s already a
command available to do this in the Log File Viewer window accessible from the View
History command on the selected job.
</p>
        <p>
          <font face="Courier New">USE msdb<br />
SELECT<br />
   J.name, <br />
   S.step_id,<br />
   S.step_name, <br />
   H.message, <br />
   run_status = CASE H.run_status<br />
      WHEN 0 THEN 'Failed'<br />
      WHEN 1 THEN 'Succeeded'<br />
      WHEN 2 THEN 'Retry'<br />
      WHEN 3 THEN 'Canceled'<br />
      WHEN 4 THEN 'In progress'<br />
   END, <br />
   H.run_date, <br />
   H.run_time, <br />
   H.run_duration<br />
FROM sysjobhistory H<br />
   INNER JOIN sysjobsteps S ON H.step_id = S.step_id AND H.job_id =
S.job_id<br />
   INNER JOIN sysjobs J ON J.job_id = H.job_id<br />
ORDER BY H.job_id, H.run_date, H.run_time, S.step_id<br /></font>
        </p>
        <img width="0" height="0" src="http://www.damirscorner.com/aggbug.ashx?id=f8225ed1-3047-44d7-a9a2-c64badbe5d91" />
      </body>
      <title>Export SQL Server Agent job history</title>
      <guid isPermaLink="false">http://www.damirscorner.com/PermaLink,guid,f8225ed1-3047-44d7-a9a2-c64badbe5d91.aspx</guid>
      <link>http://www.damirscorner.com/ExportSQLServerAgentJobHistory.aspx</link>
      <pubDate>Wed, 22 Mar 2006 22:42:26 GMT</pubDate>
      <description>&lt;p&gt;
The following query is a good starting point if you want to export the SQL Server
Agent job history to a file and you’re still using Enterprise Manager from SQL Server
2000. In SQL Server Management Studio from SQL Server&amp;nbsp;2005 there’s already a
command available to do this in the Log File Viewer window accessible from the View
History command on&amp;nbsp;the&amp;nbsp;selected&amp;nbsp;job.
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;USE msdb&lt;br&gt;
SELECT&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;J.name,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;S.step_id,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;S.step_name,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;H.message,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;run_status = CASE H.run_status&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHEN 0 THEN 'Failed'&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHEN 1 THEN 'Succeeded'&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHEN 2 THEN 'Retry'&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHEN 3 THEN 'Canceled'&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHEN 4 THEN 'In progress'&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;END,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;H.run_date,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;H.run_time,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;H.run_duration&lt;br&gt;
FROM sysjobhistory H&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;INNER JOIN sysjobsteps S ON H.step_id = S.step_id AND H.job_id =
S.job_id&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;INNER JOIN sysjobs J ON J.job_id = H.job_id&lt;br&gt;
ORDER BY H.job_id, H.run_date, H.run_time, S.step_id&lt;br&gt;
&lt;/font&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.damirscorner.com/aggbug.ashx?id=f8225ed1-3047-44d7-a9a2-c64badbe5d91" /&gt;</description>
      <comments>http://www.damirscorner.com/CommentView,guid,f8225ed1-3047-44d7-a9a2-c64badbe5d91.aspx</comments>
      <category>Development</category>
      <category>Development/SQL</category>
    </item>
  </channel>
</rss>