【问题标题】:Send a empty DateTime value into SQL stored procedure. But not null将空的 DateTime 值发送到 SQL 存储过程。但不为空
【发布时间】:2013-01-22 12:03:20
【问题描述】:

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

@pmNext_Check_Date DATETIME=NULL

我想在3个场景中使用这个参数:

  1. 如果为 NULL,则不要更新任何记录
  2. 如果它有日期值,则更新我在 WHERE 子句中指定的所有记录
  3. 问题一!对于 WHERE 子句中的记录,将查询中的所有日期字段设置为 NULL。

这是 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 2012 年 12 月 12 日

2 空

在场景 1 中,我不会传入参数,因为该过程将使用默认值并且不会更新任何日期。

在场景 2 中,我传入一个日期值并使用日期值更新两行

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

所以,我想将一个空白日期传递给存储过程。我正在使用 C# 执行此操作,并希望执行以下操作:

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

这失败了,因为 SP 需要一个 DateTime。

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

IF @pmNext_Check_Date =''

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

【问题讨论】:

  • 我假设您尝试发送 DBNull.Value,对吧?
  • 是的,我试过了。这和使用默认值是一样的
  • 您可以尝试发送 mindate 或 maxdate 并在您的 SP 中读取它
  • 我希望空白日期的值类似于 '',我可以在我的 SP 中检查它。所以有点像字符串 Null 与空字符串不同。我不会将 '' 插入数据库。我想检查那个值然后插入 null。
  • 除非您使用的是我从未听说过的 SQL Server 版本,否则添加另一个参数不会增加成本(如果您处于任何实际限制关于允许的参数数量,您还有其他问题)。只需在过程中添加另一个命名良好的参数即可。

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


【解决方案1】:

没有所谓的“空白日期”。您可以使用一个众所周知的标记值(例如,某个任意古代年份的 1 月 1 日),但 null 更可取。请注意,要通过参数传递显式 null,您需要:

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

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

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

【讨论】:

    【解决方案2】:

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

    Sql Server string to date conversion

    【讨论】:

    • 是的,这是我和一位同事一直在讨论的 2 个选项。我们只是希望有一个更好的方法,因为我们有更多的 4 个日期列要更新,这意味着 4 个额外的参数。
    • @user1131657 嗯;参数很便宜
    【解决方案3】:

    抱歉,没有办法完全按照您的要求进行操作。 DATETIME 值是 NULL 或有效日期,没有像字符串那样的“空”。

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

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

    【讨论】:

      【解决方案4】:

      如果我没记错的话,具有 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  
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多