У меня есть следующий SQL:
CREATE TABLE tbFoo(
a varchar(50) NULL,
)
CREATE NONCLUSTERED INDEX IX_tbFoo_a ON tbFoo
(
a ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
insert into tbFoo select null
insert into tbFoo select 'test'
Два следующих запроса работают нормально и используют мой индекс, как ожидалось:
select * from tbFoo where a='test'
select * from tbFoo where a is null
Теперь давайте сделаем вид, что хочу сохранить свое значение сравнения в переменной, например:
declare @a varchar(50)
select @a = NULL
Следующий запрос не возвращает ожидаемые результаты select * from tbFoo, где a = @ a, потому что я должен использовать оператор «is», а не «=»,
select * from tbFoo where (a is null and @a is null) or (a=@a)
Следующее будет работать, но будет выполнять сканирование таблицы, если @a является нулевым (из-за строки «test», которая заставляет оценивать вторую скобку)
select * from tbFoo where (a is null and @a is null) or (@a is not null and a=@a)
В конце концов, я придумал это решение, которое отлично работает и использует мой индекс:
CREATE UNIQUE NONCLUSTERED INDEX IX_tbFoo_a
ON tbFoo (a)
WHERE a IS NOT NULL;
Правильно ли мой анализ ситуации?
Есть ли лучший способ справиться с этой ситуацией?