Jeff's SQL Server Blog

Random Thoughts & Cartesian Products with Microsoft SQL Server
posts - 157, comments - 2686, trackbacks - 64

My Links

Advertisement

News

Welcome to my weblog. My name is Jeff Smith, I am software developer in Boston, MA and I was recently named a 2009 SQL Server MVP. Check in frequently for tips, tricks, commentary and ideas on SQL Server and .NET programming.


Subscribe





Archives

Post Categories

Programming

Sports

SQL

Date Only and Time Only data types in SQL Server 2005 (without the CLR)

In this post, I showed a simple way to create simple but useful Date and Time user-defined data types in SQL Server 2000.  Here's how to do it in SQL Server 2005, without the need for CLR types or anything fancy.

First, we must create two user defined data types:

create type Date from dateTime
create type Time from dateTime

So, internally (and externally to our clients), these types are really just DateTime.  But, we will apply some rules to these types so that the Date data type will always be constrained to a time exactly at midnight, and the the Time data type will always be at the "base date", or 1900-01-01:

create rule DateOnlyRule as
  dateAdd(dd,datediff(dd,0,@DateTime),0) = @DateTime

go

create rule TimeOnlyRule as
  datediff(dd,0,@DateTime) = 0
 
go

Finally, we call sp_bindrule to bind the rules to the data types:

EXEC sp_bindrule 'DateOnlyRule', 'Date'
EXEC sp_bindrule 'TimeOnlyRule', 'Time'

That's it!  Now, we can create a table that uses our brand-new data types:

create table Trans
(
 TranID int identity primary key,

 TranAmount money not null,
 TranDate Date not null,
 TranTime Time not null
)

 
Notice that TranDate and TranTime are two separate columns here.   If we try to insert data, our rules will ensure that our TranDate and TranTime columns only contain the appropriate data, and by doing so we can simply calculate TranDate + TranTime to get the transactions DateTime.

The following inserts will succeed:

insert into Trans (TranAmount, TranDate, TranTime)
values (200, '2005-01-01', '09:00:00 AM')

insert into Trans (TranAmount, TranDate, TranTime)
values (400, '2005-01-03', '7:50:30 PM')

But this will fail, since our rules are violated (getdate() returns the current date and the time):

insert into Trans (TranAmount, TranDate, TranTime)
values (200, getdate(), getdate())

Msg 513, Level 16, State 0, Line 1
A column insert or update conflicts with a rule imposed by a previous CREATE RULE statement. The statement was terminated. The conflict occurred in database 'PlayGround', table 'dbo.Trans', column 'TranDate'.
The statement has been terminated.

Finally, we can select from our table and simply add the two columns together to get each transaction's DateTime:

select *, TranDate + TranTime as TranDateTime
from Trans

TranID  TranAmount   TranDate            TranTime            TranDateTime
------- -----------  ------------------- ------------------- -------------------
1       200.00       2005-01-01 00:00:00 1900-01-01 09:00:00 2005-01-01 09:00:00
2       400.00       2005-01-03 00:00:00 1900-01-01 19:50:30 2005-01-03 19:50:30

(2 row(s) affected)

The nice advantage of doing this is that you can quickly and efficiently select all transactions for a single day like this:

select * from Trans
where TranDate = '2005-01-01'

If we stored the Date and Time in the same column, we'd need to use a less efficient range:

select * from Trans
where TranDate >= '2005-01-01' and TranDate < '2005-01-02'

SQL 2008 does finally implement true Date and Time data types, but until then, I hope this gives you some ideas to play with.

Notes:
  • If you do wish to break apart DateTime data into two columns, another option is to simply use a single, standard DateTime column but then define two extra computed columns in your table, one that returns just the Date, another that returns just the Time.  Then, you can index those computed columns and reference them easily and efficiently.  If you truly wish to store just a date or just a time, however, these user defined data types are a great way to do it.  At the end of this SQLTeam article there's a good example demonstrating this.

  • You could also just use the expressions for the rules in CHECK constrains on individual table columns, instead of creating the user defined data types and rules.  As Books On Line states, CREATE RULE will at some point be removed from future versions of SQL Server, so you may wish to avoid using it. 
see also:

Print | posted on Wednesday, October 31, 2007 9:13 AM | Filed Under [ Techniques SQL Server 2005 DateTime Data ]

Feedback

Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

no jeff, no!!
don't go tho the dark side :)))
10/31/2007 10:48 AM | Mladen
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

I thought the "dark side" was CLR integration?
10/31/2007 11:10 AM | Jeff
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

Hi Jeff

I think the SQL Server UDTs are pretty tame unless you use rules. However (from BoL 2005):

This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature. Use CHECK constraints instead. For more information, see Constraints.


A shame because UDTs could be pretty powerful otherwise. This entry is a little stronger than the 2000 entry. I don't know what BoL 2008 has to say on the matter.
10/31/2007 12:13 PM | pootle_flump
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

> I thought the "dark side" was CLR integration?

well not anymore... katmai will have at least 2 native CLR datatype that i can remember.
10/31/2007 7:18 PM | Mladen
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

Interesting approach - one that I never would have thought of today since rules have been deprecated for so long. I like it though!

I have to say that I wouldn't use UDTs even if they weren't being deprecated because they are impossible to use in a production environment. Once you define a UDT, you cannot under any circumstances change its definition; your only choice is to drop it and rebuild it. What effect would that have on your application? Several hundred thousand dollars worth of effect if I had to guess.
11/1/2007 12:45 PM | Scott Whigham
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

this article is very helpful
12/23/2007 1:51 AM | ahmed ibrahim
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

Hi,

I would like to know if i can get only the date part from a datetime value from database.
for ex: for 1/25/2008 i would like to get only '1'.
3/20/2008 3:39 AM | Aneesh
Gravatar

# time computation

Hi!

Can you pls. help me?

i have a problem in time computation....
this is the scene...

account_name Time_IN Time_Out
shena 05-01-2008 17:00 05-02-2008 8:45

how can i compute the time if i only do the work from 17:00 to 18:00 of 05-01 and 8:00 to 8:45 of 05-02

thanks....
5/4/2008 10:03 PM | Shena
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

i want to separate date and time from a single column, how can i do this.?
9/29/2008 5:17 AM | vibhanshu sahu
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

Thanks for the good post. Interesting way of getting the time value.

Hopefully SQL 2008 will have an easy way to store Time values.
11/18/2008 1:35 PM | Autosurf Restarter
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

Little bit confused...
1/10/2009 4:40 AM | murthy
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

sir i want to insert this from parameter

param = cmd1.Parameters.Add("@totaloutput", SqlDbType.Time1:Datetime);

param.Value =Convert.Time1:Datetime(Txtworktime.Text);

this is used to insert from user form in asp.net
i have create the function in c#
1/22/2009 7:53 PM | vikram malhotra
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

vikram -- I have no idea what that "Time1:DateTime" is ... my advice: consult a C#/asp.net programming book or website and learn the basics.
1/25/2009 12:37 PM | Jeff S
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

The data type is working but when i m inserting value through .net 3.5 it shows error : incorrect syntax near '12'
11/13/2009 2:26 AM | kundan
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)

Do the world a favor!!
Dont ever try to be a teacher!!!
12/13/2009 1:20 AM | Tom
Gravatar

# re: Date Only and Time Only data types in SQL Server 2005 (without the CLR)


WHERE [Timestamp] >=dateadd(day,datediff(day,0,GetDate())- 3,0) and DATEPART(HOUR, [TimeStamp]) = 02

-- [Timestamp] between (getdate() - 1) and getdate()

order by [Timestamp] desc

------- this clouse will give you last 2 days data with time if you want to compare on the basis of time use Datepart
------- whrere timestamp is your col name
2/9/2010 3:34 AM | Shakti Khurana
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET