2010-02-12 3 views
3

У меня есть форма поиска на веб-сайте, где я должен выполнить поиск во всех или в одном столбце базы данных. У меня есть следующая хранимая процедура и проблема с datetime. Как сделать, чтобы он был пустым?Сохраненная процедура, 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 '%'[email protected]+'%' AND P.Mailto LIKE '%'[email protected]+'%' 
AND P.Date LIKE '%'[email protected]+'%' AND U.UserName LIKE '%'[email protected]+'%' 
GROUP BY P.Message, P.Mailto, P.[Date], U.UserName 

Это мой код при нажатии кнопки поиска. Но я получил ошибку, если в текстовом поле нет даты ... Postit p = new Postit(); DateTime dt = DateTime.Parse (TextBoxDate.Text); p.SearchPostit (TextBoxMessage.Text, TextBoxWriter.Text, TextBoxMailto.Text, dt);

ответ

0

Вы можете изменить свое положение где что-то вроде

WHERE P.message LIKE '%'[email protected]+'%' 
AND  P.Mailto LIKE '%'[email protected]+'%' 
AND  (
       @date IS NULL 
      OR P.Date = @date 
     ) 
AND  U.UserName LIKE '%'[email protected]+'%' 
+0

Это работает в моей хранимой процедуре, но я буду делать в кодебе .... когда текстовое поле для datetime пустое ... оно не принимает значение null для datetime? –

+0

Это мой код при нажатии кнопки поиска. Но я получил ошибку, если в текстовом поле нет даты. Postit p = new Postit(); DateTime dt = DateTime.Parse (TextBoxDate.Text); p.SearchPostit (TextBoxMessage.Text, TextBoxWriter.Text, TextBoxMailto.Text, dt); –

+0

может быть лучше добавить код в исходный вопрос, чтобы он не остался незамеченным. –

0

Если я вас правильно понял вы хотите иметь что-то вроде (P.Date LIKE.... OR @date IS NULL). Вы также можете заменить часть LIKE конструкцией BETWEEN или> =/< = при работе с DATETIME. Однако, глядя на ваше утверждение, часть AND U.UserName LIKE... превращает LEFT JOIN в INNER JOIN, и вся статья WHERE со всеми LIKE полностью уничтожит вашу производительность.

0

Я по умолчанию значение null и затем обрабатываю нулевой регистр в предложении where, которое должно обрабатывать моменты, когда вы не указываете дату.

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 '%'[email protected]+'%' AND 
     P.Mailto LIKE '%'[email protected]+'%' AND 
     ((@date is null) or (P.Date LIKE '%'[email protected]+'%')) AND 
     U.UserName LIKE '%'[email protected]+'%' 
GROUP BY P.Message, P.Mailto, P.[Date], U.UserName 
+0

The = null не объявляет его как nullable, а назначает ему значение по умолчанию, которое действительно не нужно. –

+0

Спасибо, Фрэнк, должно быть потому, что он ленив и не пропускает «нулевое» значение с помощью кода. Я просто опускаю это полностью в свою цель. Я уточню свой ответ. – Mauro

1

Метод DateTime.Parse() требует строки даты в определенном формате. Пустая строка TextBox - это только "", которая, как вы указали, терпит неудачу. Альтернативой может быть использование метода DateTime.TryParse(), который не будет терпеть неудачу в случае, если строка TextBox пуста. Получаемый объект времени 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); 

ИСПАНИИ, возможно, потребуется изменить, если использовать вышеупомянутый метод, чтобы принять во внимание дату 01-JAN-0001, если вам нужно.

В качестве альтернативы вы можете передать 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 = "%"[email protected]+"%" 

    -- 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 
+0

как о (в коде C#), устанавливая значение datetime как значение NULL, а также при передаче параметра, оно также равно NULL, поэтому при сбое анализа у вас есть значение null. –

+0

Что-то вроде этого http://stackoverflow.com/questions/192121/how-do-i-use-datetime-tryparse-with-a-nullabledatetime/192146 – Ahmad

1

В C#, используйте обнуляемого DateTime.Так что-то вроде:

DateTime parsedDateValue; 
DateTime? dateValue = null; 

If (DateTime.TryParse(DateTextBox.Text, out parsedDateValue) 
    dateValue = parsedDateValue; 

Вам нужен Ненулевые DateTime исключительно для использования в качестве выходного параметра в функции TryParse. Использование классов DbCommand и DbParameters будет преобразовывать нулевое значение DateTime? значение для нулевой базы данных для вас.

Что касается хранимой процедуры, я не уверен, что вы пытаетесь выполнить с помощью: P. [Date] Like '%' + @ date + '%'. Если вы используете (@Date Is Null или P. [Date] = @Date), а @Date не является нулевым, тогда вы вернете только значения, которые точно равны P. [Date]. Вы должны быть осторожны с сопоставлениями равенства в датах, когда значения передаются из .NET из-за точности (.NET выходит на наносекунды, тогда как стандартные столбцы SQL Server DateTime выходят только до 300 мс). Если вы пытаетесь найти все значения на данный день, вы делаете что-то вроде:

( 
@Date Is Null Or 
    (P.[Date] >= Cast(DateDiff(d, 0, @Date) As DateTime) 
    And 
    P.[Date] < Cast(DateDiff(d, 0, @Date) + 1 As DateTime) 
    ) 
) 

Идея заключается в том, чтобы лишить элемент времени от прошедшего @date параметра. Вы можете сделать это, найдя количество дней от нуля заданной даты и затем переведя это число на дату. Точно так же вы хотите, чтобы конечная точка вашего диапазона была полночь на следующий день. Это означает поиск всех значений, где дата больше или равна полуночи в @Date и менее полуночи на следующий день.