Хранимая процедура, дата и время - PullRequest
3 голосов
/ 12 февраля 2010

У меня есть форма поиска на веб-сайте, где я должен выполнить поиск по всем или по одному столбцу в базе данных. У меня есть следующая хранимая процедура и проблема с 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

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

Ответы [ 5 ]

1 голос
/ 18 февраля 2010

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

DateTime parsedDateValue;
DateTime? dateValue = null;

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

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

Что касается хранимой процедуры, я не уверен, что вы пытаетесь выполнить с помощью: P. [Date] Как и '%' + @ date + '%'.Если вы используете (@Date Is Null Or P. [Date] = @Date), а @Date не равно NULL, вы будете возвращать только те значения, которые в точности равны 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 и меньше полуночи следующего дня.

1 голос
/ 17 февраля 2010

Для метода 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);

SP может потребоваться изменить, если вы используете вышеуказанный метод, чтобы принять во внимание дату 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 = "%"+@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
0 голосов
/ 12 февраля 2010

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

0 голосов
/ 12 февраля 2010

Я устанавливаю значение по умолчанию равным пустому значению, а затем обрабатываю нулевой регистр в предложении 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 '%'+@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
0 голосов
/ 12 февраля 2010

Вы можете изменить выражение where на что-то вроде

WHERE   P.message LIKE '%'+@message+'%' 
AND     P.Mailto LIKE '%'+@mailto+'%'  
AND     (
                @date IS NULL 
            OR  P.Date = @date
        )
AND     U.UserName LIKE '%'+@writer+'%' 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...