О вреде NULL

Давайте рассмотрим следующую ситуацию: у нас есть информация о поставщиках (название и город) и о покупателях (ФИО и город).

CREATE TABLE #Vendor
    (
      Name NVARCHAR(15)
    , City NVARCHAR(15)
    )
CREATE TABLE #Customer
    (
      Name NVARCHAR(15)
    , City NVARCHAR(15)
    )

Есть в Моске одна компания «Рога и копыта» (далее по тексту Р&К):

INSERT  #Vendor ( Name , City ) VALUES ( 'Рога и копыта' , 'Москва' )

Эта компания хочет начать экспансию в другие регионы (не в Москву), и при этом готова работать с кем угодно, главное, чтобы не из Киева. Понятно, что такие условия во многом выдуманные и бессмысленные (ну а какими ещё им быть, если они основаны на политических мотивах), но для нашего рассмотрения они подходят идеально. Запрос для поиска подходящих клиентов тривиален:

SELECT
    v.Name AS 'VendorName'
  , c.Name AS 'ClientName'
FROM
    #Vendor AS v
  , #Customer AS c
WHERE
    ( v.Name = 'Рога и копыта' )
    AND (
          ( v.City <> c.City )
          OR ( c.City <> 'Киев' )
        )

Рассмотрим одного очень богатого кочевника Тыгындыка:

INSERT  #Customer ( Name , City ) VALUES ( 'Тыгындык' , NULL )

Место его жительства нам не известно. Но давайте проверим, является ли он потенциальным клиентом для Р&К: если он живёт в Киеве, то является потенциальным клиентом по первому условию (v.City <> c.City), если же он живёт в любом(!) другом городе, то он является потенциальным клиентом по второму условию (c.City <> ‘Киев’). Тем не менее, указанный выше тривиальный запрос не вернёт нам Тыгындыка.
Всё дело в том, как работает трёхзначная логика:

Условие Результат Пояснение
v.City <> c.City UNKNOWN Любое сравнение с NULL всегда UNKNOWN, потому что NULL трактуется, как «неизвестно»
c.City <> ‘Киев’ UNKNOWN Любое сравнение с NULL всегда UNKNOWN, потому что NULL трактуется, как «неизвестно»

( v.City <> c.City )

OR ( c.City <> ‘Киев’ )

UNKNOWN Так как обе логические величины UNKNOWN, то и OR над ними тоже UNKNOWN.

( v.Name = ‘Рога и копыта’ )

AND ( ( v.City <> c.City ) OR ( c.City <> ‘Киев’ ) )

UNKNOWN Если немного подумать, станет очевидно, что TRUE И UNKNOWN тоже UNKNOWN

То есть по строгим правилам трёхзначной логики, Тыгындык не является потенциальным клиентам для Р&К, но в тоже самое время выше я показал, что с точки зрения общечеловеческой логики он вполне подходит под заданные критерии.
Т.о. бизнес потерял клиента только потому, что кто-то не написал NOT NULL при объявлении таблицы.

Добавить комментарий