C# 存储过程,日期时间

C# 存储过程,日期时间,c#,sql,stored-procedures,C#,Sql,Stored Procedures,我在一个网站上有一个搜索表单,我必须在数据库的所有或一列中进行搜索。我有以下存储过程,并且datetime有问题。我将如何允许它为空 我在存储过程和c#代码背后都有这个问题 希望你能帮助我 ALTER PROCEDURE [dbo].[SearchPostit] ( @message varchar(1000)='', @writer varchar(50)='', @mailto varchar(100)='', @date Datetime ) AS SELECT P.Messa

我在一个网站上有一个搜索表单,我必须在数据库的所有或一列中进行搜索。我有以下存储过程,并且datetime有问题。我将如何允许它为空

我在存储过程和c#代码背后都有这个问题

希望你能帮助我

ALTER PROCEDURE [dbo].[SearchPostit] ( 
@message varchar(1000)='', 
@writer varchar(50)='', 
@mailto varchar(100)='', 
@date Datetime ) AS 
SELECT  P.Message AS Postit, 
        P.Mailto AS 'Mailad till', 
        P.[Date] AS Datum , 
        U.UserName AS Användare
FROM PostIt P  LEFT OUTER JOIN 
     [User] U ON P.UserId=U.UserId

WHERE P.message LIKE '%'+@message+'%' AND P.Mailto LIKE '%'+@mailto+'%' 
AND P.Date LIKE '%'+@date+'%' AND U.UserName LIKE '%'+@writer+'%'
GROUP BY P.Message, P.Mailto, P.[Date], U.UserName

这是我点击搜索按钮时的代码隐藏。但如果文本框中没有日期,我会收到错误消息。。。。posit p=新posit();DateTime dt=DateTime.Parse(TextBoxDate.Text);p、 SearchPostit(TextBoxMessage.Text,TextBoxWriter.Text,TextBoxMailto.Text,dt)

您可以将where子句更改为

WHERE   P.message LIKE '%'+@message+'%' 
AND     P.Mailto LIKE '%'+@mailto+'%'  
AND     (
                @date IS NULL 
            OR  P.Date = @date
        )
AND     U.UserName LIKE '%'+@writer+'%' 

如果我理解正确,您希望有类似于
(p.Date如….或@Date为空)
。您可能还想用BETWEEN或>=/替换类似的部分。我将该值默认为null值,然后在where子句中处理null大小写,该子句应处理不指定日期的时间

ALTER PROCEDURE [dbo].[SearchPostit] (
@message varchar(1000)='',
@writer varchar(50)='',
@mailto varchar(100)='',
@date Datetime = null ) AS
SELECT  P.Message AS Postit,
        P.Mailto AS 'Mailad till',
        P.[Date] AS Datum ,
        U.UserName AS Användare
FROM PostIt P  LEFT OUTER JOIN
     [User] U ON P.UserId=U.UserId

WHERE
      P.message LIKE '%'+@message+'%' AND
      P.Mailto LIKE '%'+@mailto+'%' AND
      ((@date is null) or (P.Date LIKE '%'+@date+'%')) AND
      U.UserName LIKE '%'+@writer+'%'
GROUP BY P.Message, P.Mailto, P.[Date], U.UserName
DateTime.Parse()
方法需要特定格式的日期字符串。空文本框字符串只是一个
,正如您所指出的那样,它是失败的。另一种方法是使用
DateTime.TryParse()
方法,该方法在文本框字符串为空时不会失败。结果DateTime对象将设置为默认值,即
01-Jan-0001
。要考虑的另一个方面是,您希望日期输入为空/空多长时间。

但是,在这种情况下,将始终向sp传递一个值

DateTime dt=DateTime.Parse(TextBoxDate.Text) // fails if text is empty
但是,如果先初始化
DateTime
对象

DateTime dt = new DateTime();
dt = DateTime.Parse(TextBoxDate.Text)   // would fail if text is empty
DateTime.TryParse(TextBoxDate.Text, out dt) // would NOT fail if text is empty string
使用以下代码:

DateTime dt;
DateTime.TryParse(TextBoxDate.Text, out dt);
如果您使用上述方法来考虑0001年1月1日的日期(如果需要),则sp可能需要更改

或者,您可能希望将DateTime作为字符串传递给sp。这需要您接受varchar而不是SQL DateTime,并相应地更改sp


另一方面,我们来看看这个经过轻微修改的SP

        ALTER PROCEDURE [dbo].[SearchPostit] ( 
@message varchar(1000), 
@writer varchar(50), 
@mailto varchar(100), 
@date Datetime ) AS

DECLARE @msg varchar(1002)
DECLARE @wrt varchar(52)
DECLARE @mlt varchar(102)
DECLARE @dte DateTime

IF (@message IS NULL)
BEGIN
    SET @msg = null
END
ELSE
    SET @msg = "%"+@message+"%"

    -- similar for mailto, writer values, there is probaby a cleaner way to do this though

IF (@date is not null)
BEGIN
    SET @ dte = CONVERT(Datetime, @date, 101) 
END 



SELECT  P.Message AS Postit, 
        P.Mailto AS "Mailad till", 
        P.[Date] AS Datum , 
        U.UserName AS Användare
FROM PostIt P  
LEFT OUTER JOIN 
     [User] U ON P.UserId=U.UserId
WHERE 
    P.message   LIKE COALESCE(@msg, P.Message)  AND 
    P.Mailto    LIKE COALESCE(@lt, P.Mailto)    AND 
    P.Date      LIKE @date                      AND
    U.UserName  LIKE COALESCE(@wrt, P.UserName) 
GROUP BY P.Message, P.Mailto, P.[Date], U.UserName
在C#中,使用可为空的日期时间。比如:

DateTime parsedDateValue;
DateTime? dateValue = null;

If (DateTime.TryParse(DateTextBox.Text, out parsedDateValue)
   dateValue = parsedDateValue;
( 
@Date Is Null Or 
    ( P.[Date] >= Cast(DateDiff(d, 0, @Date) As DateTime)
    And 
    P.[Date] < Cast(DateDiff(d, 0, @Date) + 1 As DateTime)
    )
)
您需要不可为空的DateTime,只作为TryParse函数的out参数使用。使用DbCommand和DbParameters类将转换空DateTime?值设置为数据库null

关于存储过程,我不确定您使用“%”+@Date++“%”之类的:p.[Date]试图实现什么。如果使用(@Date为Null或P.[Date]=@Date)且@Date不为Null,则只返回与P.[Date]完全相同的值。由于精度的原因,在从.NET传递值的日期上,必须小心进行相等比较(.NET输出到纳秒,而标准SQL Server日期时间列仅输出到300毫秒)。如果要查找给定日期的所有值,请执行以下操作:

DateTime parsedDateValue;
DateTime? dateValue = null;

If (DateTime.TryParse(DateTextBox.Text, out parsedDateValue)
   dateValue = parsedDateValue;
( 
@Date Is Null Or 
    ( P.[Date] >= Cast(DateDiff(d, 0, @Date) As DateTime)
    And 
    P.[Date] < Cast(DateDiff(d, 0, @Date) + 1 As DateTime)
    )
)
(
@日期为空或
(P.[Date]>=Cast(DateDiff(d,0,@Date)作为DateTime)
及
P.[Date]

这里的想法是从传递的@Date参数中去掉time元素。您可以通过从给定日期的零开始查找天数,然后将该数字转换为一个日期来完成此操作。类似地,您希望范围的终点是第二天的午夜。这转化为查找日期大于或等于@date上午夜且小于次日午夜的所有值。

null不“声明为可空”,而是为其指定一个默认值,这不是真正需要的。谢谢Frank,一定是因为我很懒,不会用代码传递“null”值。我只是在我的目标中完全忽略了它。我将更新我的答案。这在我的存储过程中有效,但在codebehind中有效吗…当datetime的文本框为空时…它不接受datetime的null?这是我单击搜索按钮时的codebehind。但如果文本框中没有日期,我会收到错误消息。。。。posit p=新posit();DateTime dt=DateTime.Parse(TextBoxDate.Text);p、 SearchPostit(TextBoxMessage.Text,TextBoxWriter.Text,TextBoxMailto.Text,dt);最好是将代码添加到原始问题中,这样它就不会被忽略。如何(在C#代码中)将datetime设置为可空,并在传递参数时将其设置为可空,以便在解析失败时为空