Abhi1 Kanobi Ответов: 2

Сравнение переменных datetime в хранимой процедуре


Я пытаюсь сравнить две переменные datetime в хранимой процедуре sql server.
В приведенном ниже фрагменте кода @createdDate берется в качестве пользовательского ввода и затем сравнивается со столбцом типа datetime. Я не могу проверить свойство "="


set @sqlquery = 'Select
            v.*,
            vsc.vidhanSabhaConstituencyName, where 1=1 '

set @sqlquery = @sqlquery +'AND v.createdBy ='''+cast(@createdBy as nvarchar(100))+''''

if(@VoterIdNumber is not null)
set @sqlquery = @sqlquery+'AND v.voterIDNumber= '''+@VoterIdNumber+''''

if(@createdDate is not null)
set @sqlquery = @sqlquery+'AND v.dataIsCreated = '''+cast(@createdDate as varchar(100))+''''
else
set @sqlquery = @sqlquery+'AND v.dataIsCreated= '''+cast(getdate() as varchar(100))+'''' 

Execute sp_Executesql @sqlquery


Что я уже пробовал:

Я попытался привести и преобразовать переменную @createdDate без успеха.
Он работает с другими операторами, такими как >= или <=, но не с = .

Помощь очень ценится

F-ES Sitecore

Посмотрите, что находится в "@createdDate", посмотрите, что находится в dataIsCreated, посмотрите, что возвращается GetDate(). Это одно и то же. Буквально то же самое? Если нет, то именно поэтому ваш "=" терпит неудачу. Вы делаете предположения о вещах, поэтому решение состоит в том, чтобы выяснить, в чем заключается ваше ошибочное предположение и как его устранить. например, вы предполагаете, что 2018-03-15-это то же самое, что GetDate()? Если это так, то это предположение неверно, так как GetDate включает в себя время, поэтому 2018-03-15 не равно 2018-13-15 13:55. Это всего лишь одно из многих предположений, которые вы можете сделать, мы не можем получить доступ к вашим данным, поэтому не можем сказать наверняка.

Кроме того, не преобразуйте даты в строки, это только даст вам еще больше проблем сверху.

Abhi1 Kanobi

На самом деле проблема заключается в том , что я делаю динамический запрос на основе значений, предоставленных Пользователем . @sqlquery в задаче-это строка, которая выполняется. Все мои колонки-это дата и время .

когда я не бросаю и не сравниваю @createdDate напрямую , он выдает ошибку, как указано ниже: "типы данных nvarchar и date несовместимы в операторе add."

2 Ответов

Рейтинг:
19

Richard Deeming

Не делай этого так!

Ваш код уязвим для SQL-инъекция[^]. НИКОГДА используйте конкатенацию строк для построения SQL-запроса. ВСЕГДА используйте параметризованный запрос.

В SQL это означает использование процедуры sp_executesql[^] должным образом:

DECLARE @sqlquery nvarchar(2000);

SET @sqlquery = N'SELECT v.*, vsc.vidhanSabhaConstituencyName
FROM SomeTable As v
INNER JOIN SomeOtherTable As vsv ON <join conditions>
WHERE 1 = 1';

SET @sqlquery = @sqlquery + N' AND v.createdBy = @createdBy';

If @VoterIdNumber Is Not Null SET @sqlquery = @sqlquery + N' AND v.voterIDNumber = @VoterIDNumber';

If @createdDate Is Null SET @createdDate = GetDate();
SET @sqlquery = @sqlquery + N' AND v.dataIsCreated = @createdDate';

EXEC sp_executesql
    @sqlquery,
    N'@createdBy varchar(50), @VoterIDNumber varchar(50), @createdDate date', -- TODO: Use the correct types here
    @createdBy = @createdBy,
    @VoterIDNumber = @VoterIDNumber,
    @createdDate = @createdDate
;


Все, что вы хотели знать о SQL-инъекции (но боялись спросить) | Трой Хант[^]
Как я могу объяснить SQL-инъекцию без технического жаргона? | Обмен Стеками Информационной Безопасности[^]
Шпаргалка по параметризации запросов | OWASP[^]


Abhi1 Kanobi

Прекрасно!!! это решение работает.
Спасибо за ответ

Karthik_Mahalingam

5

Abhi1 Kanobi

- что это?

Karthik_Mahalingam

Это рейтинг для решения проблемы
5 звезд

Рейтинг:
1

OriginalGriff

Почему вы пытаетесь использовать строковые даты?
Если ваш столбец dataIsCreated имеет значение VARCHAR или NVARCHAR, то это ошибка: вместо этого сделайте его значением DATE, DATETIME или DATETIME2 и сравните значения DATE или DATETIME.

Проблема в том, что строковые даты зависят от настроек локали для машины, которая их вставила, и у вас мало контроля над этим. А даты можно вводить в трех основных форматах: гггг/ММ/ДД, ММ/ДД/гггг и ДД/ММ/гггг - поэтому, когда вы переводите свою дату в строку, у вас нет абсолютно никакого реального контроля над тем, что вы сравниваете с чем!

Храните и сравнивайте даты как даты - если вы этого не сделаете; вы создадите себе огромное количество проблем.


Abhi1 Kanobi

На самом деле проблема заключается в том , что я делаю динамический запрос на основе значений, предоставленных Пользователем . @sqlquery в задаче-это строка, которая выполняется. Все мои колонки-это дата и время .

когда я не бросаю и не сравниваю @createdDate напрямую , он выдает ошибку, как указано ниже: "типы данных nvarchar и date несовместимы в операторе add."