1

I have an SQL stored procedure which accepts a DateTime parameter which has a default value of NULL

@pmNext_Check_Date DATETIME=NULL

I want to use this parameter in 3 scenarios:

  1. If it's NULL then don't update any records
  2. If it's got a date value then update all my records specified in my WHERE clause
  3. The problem one! Set all the date fields in my query to NULL for the records in my WHERE clause.

Here is the block of code within the SP that is causing me issues (the rest of the UPDATE statement is build elsewhere in the SP and works fine):

IF @pmNext_Check_Date IS NOT NULL
    IF @pmNext_Check_Date ='' --This is the bit that is causing me a problem. I just need to check for a empty date
        SET @sql = @sql + ' Next_Check_Date = NULL '
    ELSE
        SET @sql = @sql + ' Next_Check_Date = @pmNext_Check_Date '                    

SET @sql = @sql + ' WHERE ID IN (1, 2)'

So for example if I have the following 2 rows:

ID NextCheckDate

1 12/12/12

2 NULL

In scenario 1 I wouldn't pass the parameter in as the procedure will use the default value and no dates will be updated.

In scenario 2 I pass in a date value and update both rows with the date value

In scenario 3 I want to update the date value on my rows to be null. The difference between scenario 1 & 3 is in scenario 3 the user will be choosing to set the date values to null.

So, I wanted to pass a blank date into the stored procedure. I'm doing this from C# and would like to do something like the following:

SqlParameter param = new SqlParameter("@pmNext_Check_Date", "");                            

This fails as the SP is expecting a DateTime.

So I want to be able to pass in a blank date and also how do I check this within the SP. The current check which is below doesn't work:

IF @pmNext_Check_Date =''

Thanks in advance. Hope this all makes sense. I'm using C#4.0 and SQL 2008

NoviceProgrammer
  • 3,347
  • 1
  • 22
  • 32
Sun
  • 4,458
  • 14
  • 66
  • 108
  • I assume that you tried sending in `DBNull.Value`, right? – Sergey Kalinichenko Jan 22 '13 at 12:06
  • Yes, I've tried that. That's just the same as using the default value – Sun Jan 22 '13 at 12:08
  • 1
    you can try sending mindate or maxdate and reading that in your SP – NoviceProgrammer Jan 22 '13 at 12:09
  • I would like a blank date to be value like '' which I could check within my SP. So a bit like a string Null is different to an empty string. I won't be inserting '' into the database. I want to check for that value then insert null. – Sun Jan 22 '13 at 12:12
  • I could send min/max dates but I was trying to do it a neater way really. Also the min/max date might be outside the SQL configuration range – Sun Jan 22 '13 at 12:13
  • So you want *two* "non date" values (null and empty). Why do you think that's possible? – Hans Kesting Jan 22 '13 at 12:17
  • It's possible on a string. And I don't think it's possible I was asking if anybody knew if it was possible or if there was and clever work around – Sun Jan 22 '13 at 12:22
  • 1
    Unless you're working with an edition of SQL Server I've never heard of, there's no incremental cost to *add* another parameter (if you're at any actual limit on the number of parameters allowed, you have other issues). Just add another, well named, parameter to the procedure. – Damien_The_Unbeliever Jan 22 '13 at 13:02

4 Answers4

7

There is no such thing as a "blank date". You could use a well-known sentinel value (01 Jan for some arbitrary ancient year, for example), but null would be preferable. Note that to pass an explicit null via a parameter, you need:

SqlParameter param = new SqlParameter("@pmNext_Check_Date", DBNull.Value);

If that doesn't have enough granularity, consider adding a separate boolean (bit) parameter (or similar) that clarifies what you want the sproc to do. Or: have multiple procs to do these different things.

One useful sentinel value for SQL Server is January 1, 1753 (SQL Server's minimum datetime value) - this can be produced in TSQL without string parsing as cast(-53690 as datetime).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
1

You can't pass an empty string as a datetime. So, you have a couple options. You could add an additional parameter to indicate whether or not an update should occur. I suggest that as the best options for code readability and maintainability. The other option would be to pass in the parameter as a string and parse it. That way you could use your empty string concept.

Sql Server string to date conversion

Community
  • 1
  • 1
Brian P
  • 1,569
  • 13
  • 23
  • Yeah, these were the 2 options myself and a colleague have been discussing. We were just hoping for a nicer way really as we have more 4 date columns to be updated and that will mean 4 extra parameters. – Sun Jan 22 '13 at 12:20
  • 2
    @user1131657 meh; parameters are cheap – Marc Gravell Jan 22 '13 at 12:26
1

Sorry, there is no way to do precisely what you're asking. A DATETIME value is either NULL or a valid date, there is no "empty" like there is with strings.

Another workaround is to pass a token value (that wouldn't be a valid date otherwise) to represent your so-called empty string, e.g. a common one I've seen used is 1900-01-01. Then you can differentiate in your stored procedure between NULL and "empty."

But I don't recommend doing this at all. I agree with the other suggestions: add another parameter and do the logic in a more meaningful way in the stored procedure.

Aaron Bertrand
  • 272,866
  • 37
  • 466
  • 490
0

If I can recall correctly, columns with a DATETIME datatype which allow NULLS will default to the value 1900-01-01 instead of a BLANK value.

For example: NULLS may be allowed for certain columns which might receive a value later down the line based on some kind of business logic. I have seen folks keep these open ended columns as varchar to enable a custom entry of some type or an empty string, something which datetime will not allow.

If you ask me I'd try not to mess around with the base column's data type and let it remain as DATETIME. For data retrieval and reporting purposes we might try the following approach, which may not be the best way to do it. But it works.

BEGIN
            DECLARE @VarcharDateTable TABLE
            ([EndDate_Varchar] varchar(27))

        BEGIN
                INSERT INTO @VarcharDateTable([EndDate_Varchar])
            SELECT 
              CONVERT(varchar(27), [EndDate_Datetime], 121)        
                FROM [dbo].[MainTable]
        END
        BEGIN
        SELECT CASE WHEN [EndDate_Varchar] LIKE '1900-01-01%'
                        THEN 'Data unavailable'--or whatever you want
                        ELSE [EndDate_Varchar]
                   END AS [EndDate_Varchar] FROM @VarcharDateTable
        END 
END