将空DateTime值发送到SQL存储过程。但不是空的

时间:2013-01-22 12:03:21

标签: c# sql-server-2008 datetime sqlparameter

我有一个SQL存储过程,它接受一个默认值为NULL

的DateTime参数
@pmNext_Check_Date DATETIME=NULL

我想在3种情况下使用此参数:

  1. 如果它为NULL则不更新任何记录
  2. 如果有日期值,则更新我在WHERE子句中指定的所有记录
  3. 问题一!将我的查询中的所有日期字段设置为NULL,以用于WHERE子句中的记录。
  4. 以下是SP中导致我出现问题的代码块(UPDATE语句的其余部分是在SP中的其他地方构建并且工作正常):

    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)'
    

    例如,如果我有以下2行:

    ID NextCheckDate

    1 12/12/12

    2 NULL

    在方案1中,我不会传递参数,因为过程将使用默认值,并且不会更新日期。

    在方案2中,我传入一个日期值并使用日期值

    更新这两行

    在方案3中,我想将行上的日期值更新为null。方案1和方案之间的区别; 3在方案3中,用户将选择将日期值设置为空。

    所以,我想将一个空白日期传递给存储过程。我是用C#做的,想做类似下面的事情:

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

    由于SP期待DateTime,因此失败。

    所以我希望能够传递一个空白日期,以及如何在SP中检查这个。下面的当前检查不起作用:

    IF @pmNext_Check_Date =''
    

    提前致谢。 希望这一切都有意义。 我正在使用C#4.0和SQL 2008

4 个答案:

答案 0 :(得分:6)

没有“空白日期”这样的事情。你可以使用一个众所周知的哨兵值(例如,某些任意古代的01月1日),但null会更好。请注意,要通过参数传递显式null,您需要:

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

如果它没有足够的粒度,请考虑添加一个单独的布尔(bit)参数(或类似),以阐明您希望sproc执行的操作。或者:有多个触发来做这些不同的事情。

SQL Server的一个有用的标记值是1753年1月1日(SQL Server的最小datetime值) - 这可以在TSQL中生成,而不会将字符串解析为cast(-53690 as datetime)

答案 1 :(得分:1)

您无法将空字符串作为日期时间传递。所以,你有几个选择。您可以添加其他参数以指示是否应进行更新。我建议将其作为代码可读性和可维护性的最佳选择。另一种选择是将参数作为字符串传递并解析它。这样你可以使用空字符串概念。

Sql Server string to date conversion

答案 2 :(得分:1)

抱歉,没有办法准确地按照你的要求去做。 DATETIME值为NULL或有效日期,没有“空”,就像有字符串一样。

另一种解决方法是传递一个令牌值(否则不会是一个有效的日期)来表示你所谓的空字符串,例如:我见过的一个常见的是1900-01-01。然后,您可以在NULL和“空”之间区分存储过程。

但我不建议这样做。我同意其他建议:添加另一个参数并在存储过程中以更有意义的方式执行逻辑。

答案 3 :(得分:0)

如果我能够正确回忆,那么 DATETIME 数据类型的列允许 NULLS 将默认值为1900-01-01而不是BLANK值。

例如: 某些列可能会允许 NULLS ,这些列可能会根据某种业务逻辑在以后的行中接收值。我见过人们将这些开放式列保留为varchar,以启用某种类型的自定义条目或空字符串,这是datetime不允许的。

如果你问我我会尽量不搞乱基本列的数据类型,并让它保持为 DATETIME 。对于数据检索和报告目的,我们可能会尝试以下方法,这可能不是最好的方法。但它确实有效。

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