Пример трехзначной логики в SQL Server

Я понимаю, что SQL использует трехзначную логику, но мне трудно понять, как использовать это на практике, особенно почему TRUE || NULL = True и FALSE && NULL = False вместо оценки null.

Вот три значащие таблицы истинности, применяемые к SQL Server:

Tri truth tables

Я нашел пару объяснений трехзначной логики в Интернете, но я не могу найти реальных примеров кода этого в использовании. Может ли кто-нибудь показать мне пример кода с использованием трехзначной логики, чтобы помочь мне понять это немного лучше?

Ответ 1

Примером TRUE || NULL = True будет

declare @x as int = null;
if 1=1 or @x/1=1
    print 'true'

Примером FALSE && NULL = False будет

declare @x as int = null;
if not(1=2 and @x/1=1)
    print 'false'

Ответ 2

True && NULL не является ни истинным, ни ложным. Это просто NULL.

Будет ли это оцениваться как True, False или Ошибка в булевом выражении, зависит от того, что происходит в вашей системе, когда вы оцениваете NULL самостоятельно как логическое. Sql Server сделает все возможное, чтобы избежать выбора, но при принуждении вы почти никогда не увидите положительного (True) результата.

Ответ 3

Вообще говоря, с точки зрения пользователя, вы не хотите, чтобы булевское выражение оценивалось в NULL.

Написание SQL обычно включает в себя запись запросов для явного исключения значений NULL в булевых выражениях. IMX, разработчики будут рассматривать использование трехзначной логики намеренно считаться злоупотреблением трехзначной логикой. Правильно написанный запрос должен обрабатывать NULL и понимать их. Вы не пишете их таким образом, чтобы они работали правильно, когда что-то было NULL. Обычно это включает COALESCE() или IS NULL или IS NOT NULL где-то.

Однако важно, чтобы вы поняли логику, потому что NULL существуют и неизбежны для большинства реальных данных.

Например, скажем, я работаю над таблицей студентов. В таблице указаны поля First, Middle и Last name. Я хочу знать список студентов, у которых нет среднего имени. Теперь в некоторых приложениях будет храниться пустая строка '', а некоторые приложения будут хранить значение NULL, а некоторые приложения могут выполнять и (и некоторые RDBMS, такие как Oracle, обрабатывают пустые строки как NULL). Если вы не уверены, вы можете написать это как:

SELECT *
FROM Student
WHERE MiddleName = ''
    OR MiddleName IS NULL;

Другим распространенным сценарием является то, что вы ВЗАИМОДЕЙСТВУЮТСЯ в другую таблицу. Скажем, вы сравниваете зарплату учителей. У вас есть таблица для проверок и таблица для CheckDetail. Вы хотите знать, сколько учителей платят за пособия. В вашем отчете необходимо указать всех учителей, даже если они являются подрядчиками, которые не платят за пособия, потому что они не получают:

SELECT Check.Employee_Id,
    SUM(CheckDetail.Amount) AS BenefitsDeductions
FROM Check
LEFT JOIN CheckDetail
    ON  Check.Id = CheckDetail.CheckId
    AND CheckDetail.LineItemType = 'Benefits'
GROUP BY Check.Employee_Id;

Вы запускаете свой отчет, и вы замечаете, что ваши преподаватели-подрядчики показывают NULL для BenefitsDeductions. К сожалению. Вам нужно убедиться, что оно отображается как ноль:

SELECT Check.Employee_Id,
    COALESCE(SUM(CheckDetail.Amount),0) AS BenefitsDeductions
FROM Check
LEFT JOIN CheckDetail
    ON  Check.Id = CheckDetail.CheckId
    AND CheckDetail.LineItemType = 'Benefits'
GROUP BY Check.Employee_Id;

Итак, вы пытаетесь это сделать, и это работает. Нет значений NULL! Но... несколько дней спустя ваши пользователи сообщают, что учителя, которые раньше были подрядчиками, показывали с 0, даже если они платят за пособия сейчас. У вас есть COALESCE перед SUM, чтобы сохранить эти суммы:

SELECT Check.Employee_Id,
    SUM(COALESCE(CheckDetail.Amount,0)) AS BenefitsDeductions
FROM Check
LEFT JOIN CheckDetail
    ON  Check.Id = CheckDetail.CheckId
    AND CheckDetail.LineItemType = 'Benefits'
GROUP BY Check.Employee_Id;

Поиск этих типов угловых случаев и исключений - это то, что написано в SQL.

Ответ 4

Пример кода user4955163 - это отличная визуализация этого, однако я просто хотел вернуться к первому сегменту вопроса:

... особенно зачем ИСТИНА || NULL = True и FALSE && NULL = False вместо от оценки до нуля...

TRUE || NULL = True

Это связано с тем, что оператор or будет замыкаться, если один из операндов уже известен как true. Независимо от того, какой второй операнд (даже если неизвестный, т.е. "NULL" ), он не сделает выражение false, так как мы уже знаем, что другой операнд true. or нужен только один операнд true, чтобы оценить его true.

FALSE && NULL = False

Это связано с тем, что оператор and будет замыкаться, если один из операндов уже известен как false. Независимо от того, какой второй операнд (даже если неизвестный, т.е. "NULL" ), он не сделает выражение true, так как мы уже знаем, что другой операнд false. and требуется, чтобы оба операнда были true для оценки до true.

Ответ 5

Чтобы использовать переменную с нулевым значением, вам нужно просто проверить условия NULL (используя IS NULL), прежде чем проверять значение.

например. IF @a IS NOT NULL AND @a = 1