Коллектив Авторов - Базы данных: конспект лекций
Чтобы лучше понять, какие значения понимаются под неопределенными, рассмотрим таблицу, являющуюся фрагментом базы данных:
Итак, неопределенное значение или Null-значение – это:
1) неизвестное, но обычное, т. е. применимое значение. Например, у господина Хайретдинова, который является номером один в нашей базе данных, несомненно, имеются какие-то паспортные данные (как у человека 1980 г. рождения и гражданина страны), но они не известны, следовательно, не занесены в базу данных. Поэтому в соответствующую графу таблицы будет записано значение Null;
2) неприменимое значение. У господина Карамазова (№ 2 в нашей базе данных) просто не может быть никаких паспортных данных, потому что на момент создания этой базы данных или внесения в нее данных, он являлся ребенком;
3) значение любой ячейки таблицы, если мы не можем сказать применимое оно или нет. Например, у господина Коваленко, который занимает третью позицию в составленной нами базе данных, неизвестен год рождения, поэтому мы не можем с уверенностью говорить о наличие или отсутствии у него паспортных данных. А следовательно, значениями двух ячеек в строке, посвященной господину Коваленко будет Null-значение (первое – как неизвестное вообще, второе – как значение, природа которого неизвестна). Как и любые другие типы данных, Null-значения тоже имеют определенные свойства. Перечислим самые существенные из них:
1) с течением времени понимание Null-значения может меняться. Например, у господина Карамазова (№ 2 в нашей базе данных) в 2014 г., т. е. по достижении совершеннолетия, Null-значение изменится на какое-то конкретное вполне определенное значение;
2) Null-значение может быть присвоено переменной или константе любого типа (числового, строкового, логического, дате, времени и т. д.);
3) результатом любых операций над выражениями с Null-значе-ниями в качестве операндов является Null-значение;
4) исключением из предыдущего правила являются операции конъюнкции и дизъюнкции в условиях законов поглощения (подробнее о законах поглощения смотрите в п. 4 лекции № 2).
3. Null-значения и общее правило вычисления выражений
Поговорим подробнее о действиях над выражениями, содержащими Null-значения.
Общее правило работы с Null-значениями (то, что результат операций над Null-значениями есть Null-значение) применяется к следующим операциям:
1) к арифметическим;
2) к побитным операциям отрицания, конъюнкции и дизъюнкции (кроме законов поглощения);
3) к операциям со строками (например, конкотинации – сцепления строк);
4) к операциям сравнения (<, ≤, ≠, ≥, >).
Приведем примеры. В результате применений следующих операций будут получены Null-значения:
3 + Null, 1/ Null, (Иванов' + '' + Null) ≔ Null
Здесь вместо обычного равенства использована операция подстановки «≔» из-за особого характера работы с Null-значениями. Далее в подобных ситуациях также будет использоваться этот символ, который означает, что выражение справа от символа подстановки может заменить собой любое выражение из списка слева от символа подстановки.
Характер Null-значений приводит к тому, что часто в некоторых выражениях вместо ожидаемого нуля получается Null-значение, например:
(x – x), y * (x – x), x * 0 ≔ Null при x = Null.
Все дело в том, что при подстановке, например, в выражение (x – x) значения x = Null, мы получаем выражение (Null – Null), и в силу вступает общее правило вычисления значения выражения, содержащего Null-значения, и информация о том, что здесь Null-значение соответствует одной и той же переменной теряется.
Можно сделать вывод, что при вычислении любых операций, кроме логических, Null-значения интерпретируются как неприменимые, и поэтому в результате получается тоже Null-значение.
К не менее неожиданным результатам приводит использование Null-значений в операциях сравнения. Например, в следующих выражениях также получаются Null-значения вместо ожидаемых логических значений True или False:
(Null < Null); (Null ≤ Null); (Null = Null); (Null ≠ Null);
(Null > Null); (Null ≥ Null) ≔ Null;
Таким образом, делаем вывод, что нельзя говорить о том, что Null-значение равно или не равно самому себе. Каждое новое вхождение Null-значения рассматривается как независимое, и каждый раз Null-значения воспринимаются как различные неизвестные значения. Этим Null-значения кардинально отличаются от всех остальных типов данных, ведь мы знаем, что обо всех пройденных ранее величинах и их типах с уверенностью можно было говорить, что они равны или не равны друг другу.
Итак, мы видим, что Null-значения не являются значениями переменных в обычном смысле этого слова. Поэтому становится невозможным сравнивать значения переменных или выражения, содержащие Null-значения, поскольку в результате мы будем получать не логические значения True или False, а Null-значения, как в следующих примерах:
(x < Null); (x ≤ Null); (x = Null); (x ≠ Null); (x > Null);
(x ≥ Null) ≔ Null;
Поэтому по аналогии с пустыми значениями для проверки выражения на Null-значения необходимо использовать специальный предикат:
IsNull (<выражение>), что буквально означает «есть Null».
Логическая функция возвращает значение True, если в выражении присутствует Null или оно равно Null, и False – в противном случае, но никогда не возвращает значение Null. Предикат IsNull может применяться к переменным и выражению любого типа. Если применять его к выражениям пустого типа, предикат всегда будет возвращать False.
Например:
Итак, действительно, видим, что в первом случае, когда предикат IsNull взяли от нуля, на выходе получилось значение False. Во всех случаях, в том числе во втором и третьем, когда аргументы логической функции оказались равными Null-значению, и в четвертом случае, когда сам аргумент и был изначально равен Null-значению, предикат выдал значение True.
4. Null-значения и логические операции
Обычно в системах управления базами данных непосредственно поддерживаются только три логические операции: отрицание ¬, конъюнкция & и дизъюнкция ∨. Операции следования ⇒ и равносильности ⇔ выражаются через них с помощью подстановок:
(x ⇒ y) ≔ (¬x ∨ y);
(x ⇔ y) ≔ (x ⇒ y) & (y ⇒ x);
Заметим, что эти подстановки полностью сохраняются и при использовании Null-значений.
Интересно, что при помощи операции отрицания «¬» любая из операций конъюнкция & или дизъюнкция ∨ может быть выражена одна через другую следующим образом:
(x & y) ≔¬ (¬x ∨¬y);
(x ∨ y) ≔ ¬ (¬x & ¬y);
На эти подстановки, как и на предыдущие, Null-значения влияния не оказывают.
А теперь приведем таблицы истинности логических операций отрицания, конъюнкции и дизъюнкции, но кроме привычных значений True и False, используем также Null-значение в качестве операндов. Для удобства введем следующие обозначения: вместо True будем писать t, вместо False – f, а вместо Null – n.
1. Отрицание ¬x.
Стоит отметить следующие интересные моменты касательно операции отрицания с использованием Null-значений:
1) ¬¬x ≔ x – закон двойного отрицания;
2) ¬Null ≔ Null – Null-значение является неподвижной точкой.
2. Конъюнкция x & y.
Эта операция также имеет свои свойства:
1) x & y ≔ y & x– коммутативность;
2) x & x ≔ x – идемпотентность;
3) False & y ≔ False, здесь False – поглощающий элемент;
4) True & y ≔ y, здесь True – нейтральный элемент.
3. Дизъюнкция x ∨ y.
Свойства:
1) x ∨ y ≔ y ∨ x – коммутативность;
2) x ∨ x ≔ x – идемпотентность;
3) False ∨ y ≔ y, здесь False – нейтральный элемент;
4) True ∨ y ≔ True, здесь True – поглощающий элемент.
Исключение из общего правила составляют правила вычисления логических операций конъюнкция & и дизъюнкция ∨ в условиях действия законов поглощения:
(False & y) ≔ (x & False) ≔ False;
(True ∨ y) ≔ (x ∨ True) ≔ True;
Эти дополнительные правила формулируются для того, чтобы при замене Null-значения значениями False или True результат бы все равно не зависел бы от этого значения.
Как и ранее было показано для других типов операций, применение Null-значений в логических операциях могут также привести к неожиданным значениям. Например, логика на первый взгляд нарушена в законе исключения третьего (x ∨ ¬x) и в законе рефлексивности (x = x), поскольку при x ≔ Null имеем:
(x ∨ ¬x), (x = x) ≔ Null.
Законы не выполняются! Объясняется это так же, как и раньше: при подстановке Null-значения в выражение информация о том, что это значение сообщается одной и той же переменной теряется, а в силу вступает общее правило работы с Null-значениями.