Обработка IS NULL внутри строки в SQL - PullRequest
2 голосов
/ 14 сентября 2010

У меня есть SQL-запрос, который записывается в строку, а затем выполняется с помощью команды Exec (строка), например:

Declare @TestId bigint = null
Declare @Query nvarchar(max)
set @Query = 'SELECT * from Registrations where RegistrationId = 15 AND (' + CAST(@TestId AS NVARCHAR) + ' IS NULL OR TestId = ' + CAST(@TestId AS NVARCHAR) + ') '
EXEC(@Query)

Проблема теперь в том, что IS NULL неправильно анализируется внутри строки, ноКогда я удаляю IS NULL из строки, он работает правильно, а когда @TestId принимает значение, отличное от нуля, он работает правильно, когда проблема заключается в приведении IS NULL внутри строки @Query.

Примечание : @TestId - это параметр процедуры

Мне нужно знать, как заставить SQL чувствовать себя с IS NULL и правильно его анализировать

Заранее спасибо

Ответы [ 5 ]

4 голосов
/ 14 сентября 2010

Если вам действительно нужно использовать динамический sql для этого, используйте sp_executesql следующим образом:

Declare @TestId bigint = null
Declare @Query nvarchar(max)
set @Query = 'SELECT * from Registrations where RegistrationId = 15 AND (@TestId IS NULL OR TestId = @TestId)'

EXECUTE sp_executesql @Query, N'@TestId BIG INT', @TestId
1 голос
/ 14 сентября 2010

Другие ответы предоставляют решения. Вот почему ваше решение не сработало. Когда @TestId имеет значение null, вы объединяете null с вашей строкой @Query, и это присваивает значение NULL для @Query. Если вы напечатаете свой @Query вместо exec, вы увидите запрос, который будет выполняться.

Declare @TestId bigint = 10--null
Declare @Query nvarchar(max)
set @Query = 'SELECT * from Registrations where RegistrationId = 15 AND (' + CAST(@TestId AS NVARCHAR) + ' IS NULL OR TestId = ' + CAST(@TestId AS NVARCHAR) + ') '
--EXEC(@Query)
print @Query
1 голос
/ 14 сентября 2010

Для этого вам не нужен динамический SQL.Кроме того, если вам нужно было генерировать динамический SQL, одно из преимуществ этого состоит в том, что ваши запросы не должны иметь такую ​​конструкцию WHERE TestId =@TestId OR @TestId IS NULL, которая вызывает проблемы с кэшированием плана и ненужным просмотром таблиц.1004 * Редактировать

После комментария, если вам нужен динамический SQL, используйте sp_executesql и сгенерируйте различных строк для случая, когда @TestId is null.Не включайте оба случая в один и тот же запрос.

0 голосов
/ 14 сентября 2010

Из вашего кода я подозреваю, что вы хотите отфильтровать результаты регистраций по TestId, учитывая, что оно не равно нулю.Почему бы не сделать это программно, а не в запросе SQL?Что-то в этом духе (синтаксис может быть неправильным):

Declare @TestId bigint = null
Declare @Query nvarchar(max)
if(@TestId IS NULL)  
   set @Query = 'SELECT * from Registrations where RegistrationId = 15'
else
   set @Query = 'SELECT * from Registrations where RegistrationId = 15 AND (TestId = ' + CAST(@TestId AS NVARCHAR) + ') '
EXEC(@Query)

Также, Джастин Нисснер прав, следует избегать динамического SQL, если это возможно (это можно сделать без динамического SQL).

0 голосов
/ 14 сентября 2010

Построение динамических запросов - это плохо, ладно ... при этом можно исправить это, переместив пустую проверку за пределы динамического запроса и обработав ее там:

set @Query = 'select * from registrations where registrationId = 15 and
             CAST(TestId AS NVARCHAR) = ' + ISNULL(CAST(@TestId AS NVARCHAR), '')

С другой стороны, почему вы используете динамически построенный запрос для чего-то такого простого? Это может быть обычное выражение SELECT, которое сделает вещи намного менее сложными.

select * from registrations where registrationId = 15 and TestId = @TestId
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...