Ответ 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'
Я понимаю, что SQL использует трехзначную логику, но мне трудно понять, как использовать это на практике, особенно почему TRUE || NULL = True
и FALSE && NULL = False
вместо оценки null
.
Вот три значащие таблицы истинности, применяемые к SQL Server:
Я нашел пару объяснений трехзначной логики в Интернете, но я не могу найти реальных примеров кода этого в использовании. Может ли кто-нибудь показать мне пример кода с использованием трехзначной логики, чтобы помочь мне понять это немного лучше?
Примером 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'
True && NULL
не является ни истинным, ни ложным. Это просто NULL
.
Будет ли это оцениваться как True, False или Ошибка в булевом выражении, зависит от того, что происходит в вашей системе, когда вы оцениваете NULL
самостоятельно как логическое. Sql Server сделает все возможное, чтобы избежать выбора, но при принуждении вы почти никогда не увидите положительного (True) результата.
Вообще говоря, с точки зрения пользователя, вы не хотите, чтобы булевское выражение оценивалось в 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.
Пример кода 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
.
Чтобы использовать переменную с нулевым значением, вам нужно просто проверить условия NULL (используя IS NULL
), прежде чем проверять значение.
например. IF @a IS NOT NULL AND @a = 1