Вопрос сравнения T-SQL varchar - PullRequest
2 голосов
/ 04 декабря 2008

Я использую MS Sql 2005.

Почему это дает мне правильные результаты (возвращает 169 строк) ...

select
  * 
from 
  [import_Data] 
where 
  [import_Data].name not in 
  (
    select 
      [import_Data].name 
    from 
      [import_Data] 
      inner join [resource] on [import_Data].name = [resource].name
    where 
      [import_Data].ProviderTypeID = 4 
      and [resource].IsDeleted = 0
  )
  and [import_Data].ProviderTypeID = 4

Но это не так (возвращает 0 строк) ...

select 
  * 
from 
  [import_Data] 
where 
  [import_Data].name not in 
  (
    select 
      [resource].name 
    from 
      [resource] 
    where 
      IsDeleted = 0
  ) 
  and [import_Data].ProviderTypeID = 4

Единственная разница между столбцами name состоит в том, что [resource].name равен varchar(500), а [import_Data].name равен varchar(300).

Ответы [ 4 ]

6 голосов
/ 04 декабря 2008

Я предполагаю, что в вашей таблице ресурсов есть нулевое resource.name, которое отбрасывает все сравнения. Почему нулевые значения вызывают проблемы? В «Руководстве гуру к TSQL», и я перефразирую «Рекомендации ANSI утверждают, что выражение, которое сравнивает значение на равенство с NULL, всегда возвращает NULL». Таким образом, любое значение в списке сбрасывает все это.

В первом запросе ваше внутреннее объединение исключает эти нули.

Итак, у вас есть три варианта

  • Не используйте NOT IN, используйте NOT EXISTS
  • Используйте ISNULL для resource.name, чтобы исключить нули
  • Измените поведение обработки нуля, установив ANSI_NULLS OFF.

Пример не существует с использованием коррелированного подзапроса (предупреждающий код)

SELECT *
FROM [import_Data] 
WHERE NOT EXISTS(
        select [resource].name from [resource] where IsDeleted = 0 AND [resource].name = [import_Data].name
    )
  AND [import_Data].ProviderTypeID = 4
4 голосов
/ 04 декабря 2008

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

Как насчет этого:

select 
  * 
from 
  [import_Data] 
where 
  not exists 
  (
    select 1 
    from   [resource] 
    where  name = [import_Data].Name and IsDeleted = 0
  ) 
  and [import_Data].ProviderTypeID = 4
2 голосов
/ 04 декабря 2008

На самом деле проблема в том, что, похоже, в вашем столбце [resource] .name есть значения NULL.

Предложение "NOT IN" t-sql не будет работать, если в предоставленном списке значений есть значения NULL.

Это потому, что ваше где будет разрешено как:

[import_Data].name <> 'Resource1' and [import_Data].name <> 'Resource2' 
and [import_Data].name <> null

когда обработчик запросов разрешает [import_Data] .name <> null, он возвращает значение UNKNOWN, а выражение всегда оценивается как false. Следовательно, вы никогда не получите никаких строк.

Например, вы всегда получите 0 строк, если вы выполните

select * from [import_Data] where [import_Data].name <> null

Итак, учитывая это, следующий запрос, вероятно, будет работать в вашем случае:

select * from [import_Data] 
where [import_Data].name not in (
    select [resource].name from [resource] where IsDeleted = 0 
    and [resource].name is not null
) and [import_Data].ProviderTypeID = 4
2 голосов
/ 04 декабря 2008

Возможно, у вас есть null в столбце name таблицы [resource]. Поведение = и not in отличается, когда задействованы нули.

Попробуйте:

select * from [resource] where name is null and IsDeleted = 0

чтобы сузить его.

Или исправить:

select * from [import_Data]
where 
  [import_Data].name not in (
    select name from [resource] where IsDeleted = 0 and name is not null
    ) 
  and [import_Data].ProviderTypeID = 4

Также см. Предложение NOT IN и значения NULL

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...