0

We have a really stupid data requirement for dates in our database. The month, day, year, minute, & hour are stored in separate columns. Obviously, this is not ideal for querying date ranges especially using Entity Framework.

We decided to just create a new column called combinedDate that is a SQL smalldatetime with the correlating date info. While trying to update our db, our application just freezes and never completes the update. Our test db only has 8400 rows so this definitely shouldn't be a big problem.

Should we be using a stored procedure for this? What is the best approach to accomplish this?

We will have to do this to our date data for every new entry in the database. These entries could possibly happen 8400 rows at a time.

Column formats:

  • Year int = 12
  • Month int = 4
  • Day int = 27
  • Hour int = 12
  • Min int = 0

New column: smalldatetime

  • combinedDate = '2012-04-27 12:00:00 PM'
1
  • SQL = SQL Server ?? SQL really is only the Structured Query Language - not a database product... Commented Apr 27, 2012 at 19:30

4 Answers 4

1

I agree that a computed column is the best approach.

Perhaps you should consider a different angle; instead of computing the datetime, rather compute the year/month/day/hour/minute via

Year as (DATEPART('yyyy', Time)) persisted not null,
Month as (DATEPART('m', Time)) persisted not null,
Day as (DATEPART('d', Time)) persisted not null,
Hour as (DATEPART('hh', Time)) persisted not null,
Min as (DATEPART('mi', Time)) persisted not null,
Time datetime not null

Link to DATEPART documentation

That way you will automatically have the other fields validated when updating the Time column.

Disclaimer: At the time of this writing I'm unsure if DATEPART is deterministic to use persisted.

Sign up to request clarification or add additional context in comments.

1 Comment

Your DATEPARTs are not entirely correct - you should have: Year as (DATEPART(YEAR, Time)) persisted not null - first parameter is just the definition of the part, without any quotes
1

Why not use a computed column? That way you can be sure your year, month, day, hour, min and datetime fields are in sync (if you are obliged to keep the first).

1 Comment

So how do you convert these int columns to one combine datetime?
1

As others mentioned, creating a computed column would be a better choice. Completely avoiding this approach would be even better. However, if cannot avoid this approach, here is the computed column expression that you could use. In the output section you can notice, that invalid values in month and min actually add up to display the correct date in future

Computed column expression:

(dateadd(year, (100) + [year],
    dateadd(month, [month] - (1),
        dateadd(day, [day] - (1),
            dateadd(hour, [hour],
                dateadd(minute, [min], (0))
                )
            )
        )
    )
)

Sample script:

CREATE TABLE dbo.myTable
(
        [year]  int NOT NULL
    ,   [month] int NOT NULL
    ,   [day]   int NOT NULL
    ,   [hour]  int NOT NULL
    ,   [min]   int NOT NULL
    ,   [smalldatetime]  AS (dateadd(year,(100)+[year],dateadd(month,[month]-(1),dateadd(day,[day]-(1),dateadd(hour,[hour],dateadd(minute,[min],(0))))))) PERSISTED
);

INSERT INTO dbo.myTable ([year], [month], [day], [hour], [min]) VALUES
    (12, 4, 27, 17, 34),
    (12, 6, 12, 4, 8),
    (11, 32, 12, 54, 87);

SELECT  [year]
    ,   [month]
    ,   [day]
    ,   [hour] 
    ,   [min] 
    ,   [smalldatetime] 
FROM    dbo.myTable;

Sample output:

year month day hour min smalldatetime
---- ----- --- ---- --- -----------------------
12    4     27  17  34  2012-04-27 17:34:00.000
12    6    -12   4   8  2012-05-19 04:08:00.000
11    32    12  54  87  2013-08-14 07:27:00.000

Comments

0

Rather than trying to do the update from the C# side, why don't you just specify a computed column for combinedDate. Take a look at the DATETIMEFROMPARTS built-in function, it may be of use

EDIT

As was pointed out in the comments, DATETIMEFROMPARTS is available only in SQL Server 2012, here is an alternative way to get a DATETIME from parts y, m, d (assuming integers):

CAST(CAST(y AS varchar) + '-' + CAST(m AS varchar) + '-' + CAST(d AS varchar) AS DATETIME)

2 Comments

That very useful function is unfortunately available with SQL Server 2012 only - not with any version before...
Another thing: the format YY-MM-DD to create a DATETIME in SQL Server is not safe - e.g. it doesn't work under all language and dateformat settings. If you want to create a DATETIME you need to use either YYYYMMDD (without any dashes), or then YYYY-MM-DDTHH:MM:SS to make this work under all configurations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.