Неполные данные и null — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
м (Скалярные операции)
(проблемы null)
Строка 20: Строка 20:
 
* Результаты множественных операций
 
* Результаты множественных операций
 
Оказывается, что в некоторых случаях без null не обойтись и надо уметь с ним работать.
 
Оказывается, что в некоторых случаях без null не обойтись и надо уметь с ним работать.
== Операции с null ==
+
== Тернарная логика с использованием null ==
=== Тернарная логика ===
 
 
С точки зрения SQL, результат логического выражения может быть ''true'', ''false'' или ''unknown''.<br>
 
С точки зрения SQL, результат логического выражения может быть ''true'', ''false'' или ''unknown''.<br>
 
С другой стороны есть тип ''boolean'', и у него есть 3 значения: ''true'', ''false'' и '''''null''''' <br>
 
С другой стороны есть тип ''boolean'', и у него есть 3 значения: ''true'', ''false'' и '''''null''''' <br>
 
То есть формально ''unknown'' - это результат вычисления, а '''''null''''' - это конкретное значение, которое может быть записано в БД. На практике ''unknown'' представляется значением '''''null''''', и это различие не будет иметь большого значения.
 
То есть формально ''unknown'' - это результат вычисления, а '''''null''''' - это конкретное значение, которое может быть записано в БД. На практике ''unknown'' представляется значением '''''null''''', и это различие не будет иметь большого значения.
==== Логические операции ====
+
=== Конъюнкция ===
===== Конъюнкция =====
 
 
{| style="background-color:#CCC;margin:0.5px;text-align:center"
 
{| style="background-color:#CCC;margin:0.5px;text-align:center"
 
!style="background-color:#EEE;color:#00F"| <tex>\bf{and}</tex>
 
!style="background-color:#EEE;color:#00F"| <tex>\bf{and}</tex>
Строка 49: Строка 47:
 
|}
 
|}
  
===== Дизъюнкция =====
+
=== Дизъюнкция ===
 
{| style="background-color:#CCC;margin:0.5px;text-align:center"
 
{| style="background-color:#CCC;margin:0.5px;text-align:center"
 
!style="background-color:#EEE;color:#00F"| <tex>\bf{or}</tex>
 
!style="background-color:#EEE;color:#00F"| <tex>\bf{or}</tex>
Строка 72: Строка 70:
 
|}
 
|}
  
===== Отрицание =====
+
=== Отрицание ===
 
{| style="background-color:#CCC;margin:0.5px;text-align:center"
 
{| style="background-color:#CCC;margin:0.5px;text-align:center"
 
!style="background-color:#EEE;color:#00F"| <tex></tex>
 
!style="background-color:#EEE;color:#00F"| <tex></tex>
Строка 85: Строка 83:
 
|}
 
|}
  
===== Импликация =====
+
=== Сравнение ===
TODO: уточнить
+
==== = ====
* A → B = (not A) or B
+
{| style="background-color:#CCC;margin:0.5px;text-align:center"
{| style="background-color:#CCC;margin-left:2rem;text-align:center"
+
!style="background-color:#EEE;color:#00F"| <tex>\bf{=}</tex>
!style="background-color:#EEE;color:#00F"| <tex>\bf{(not\ A)\ or\ B}</tex>
 
 
!style="background-color:#EEE"| <tex>\bf{true}</tex>
 
!style="background-color:#EEE"| <tex>\bf{true}</tex>
 
!style="background-color:#EEE"| <tex>\bf{unknown}</tex>
 
!style="background-color:#EEE"| <tex>\bf{unknown}</tex>
Строка 100: Строка 97:
 
|-
 
|-
 
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{unknown}</tex>
 
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{unknown}</tex>
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
+
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
|-
 
|-
 
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{false}</tex>
 
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{false}</tex>
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
+
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
+
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|}
 
|}
  
* A → B = not (A and not B)
+
==== is ====
{| style="background-color:#CCC;margin-left:2rem;text-align:center"
+
{| style="background-color:#CCC;margin:0.5px;text-align:center"
!style="background-color:#EEE;color:#00F"| <tex>\bf{not\ (A\ and\ not\ B)}</tex>
+
!style="background-color:#EEE;color:#00F"| <tex></tex>
 
!style="background-color:#EEE"| <tex>\bf{true}</tex>
 
!style="background-color:#EEE"| <tex>\bf{true}</tex>
 
!style="background-color:#EEE"| <tex>\bf{unknown}</tex>
 
!style="background-color:#EEE"| <tex>\bf{unknown}</tex>
 
!style="background-color:#EEE"| <tex>\bf{false}</tex>
 
!style="background-color:#EEE"| <tex>\bf{false}</tex>
 
|-
 
|-
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{true}</tex>
+
|style="background-color:#EEE;color:#00F;;padding:2px 30px"| <tex>\bf{is\ true}</tex>
 +
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 +
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 +
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 +
|-
 +
|style="background-color:#EEE;color:#00F;;padding:2px 30px"| <tex>\bf{is\ unknown}</tex>
 +
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
 
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 
|-
 
|-
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{unknown}</tex>
+
|style="background-color:#EEE;color:#00F;;padding:2px 30px"| <tex>\bf{is\ false}</tex>
 +
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 +
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 +
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 +
|-
 +
|style="background-color:#EEE;color:#00F;;padding:2px 30px"| <tex>\bf{is\ not\ true}</tex>
 +
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 +
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
 
|-
 
|-
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{false}</tex>
+
|style="background-color:#EEE;color:#00F;;padding:2px 30px"| <tex>\bf{is\ not\ unknown}</tex>
 +
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 +
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 +
|-
 +
|style="background-color:#EEE;color:#00F;;padding:2px 30px"| <tex>\bf{is\ not\ false}</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 +
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 
|}
 
|}
Оказывается что законы Де Моргана в данном случае '''не работают'''.
+
== Проблемы при работе с null ==
 
+
При работе с '''null''' в процессе разработки БД, во избежание непредвиденных ошибок, необъодимо заранее ознакомиться с тем, какие проблемы могут возникнуть.
==== Сравнение ====
+
=== Неоднозначность импликации ===
===== = =====
+
TODO: уточнить
{| style="background-color:#CCC;margin:0.5px;text-align:center"
+
* A → B = (not A) or B
!style="background-color:#EEE;color:#00F"| <tex>\bf{=}</tex>
+
{| style="background-color:#CCC;margin-left:2rem;text-align:center"
 +
!style="background-color:#EEE;color:#00F"| <tex>\bf{(not\ A)\ or\ B}</tex>
 
!style="background-color:#EEE"| <tex>\bf{true}</tex>
 
!style="background-color:#EEE"| <tex>\bf{true}</tex>
 
!style="background-color:#EEE"| <tex>\bf{unknown}</tex>
 
!style="background-color:#EEE"| <tex>\bf{unknown}</tex>
Строка 148: Строка 161:
 
|-
 
|-
 
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{unknown}</tex>
 
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{unknown}</tex>
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
+
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
|-
 
|-
 
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{false}</tex>
 
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{false}</tex>
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
+
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
+
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|}
 
|}
  
===== is =====
+
* A → B = not (A and not B)
{| style="background-color:#CCC;margin:0.5px;text-align:center"
+
{| style="background-color:#CCC;margin-left:2rem;text-align:center"
!style="background-color:#EEE;color:#00F"| <tex></tex>
+
!style="background-color:#EEE;color:#00F"| <tex>\bf{not\ (A\ and\ not\ B)}</tex>
 
!style="background-color:#EEE"| <tex>\bf{true}</tex>
 
!style="background-color:#EEE"| <tex>\bf{true}</tex>
 
!style="background-color:#EEE"| <tex>\bf{unknown}</tex>
 
!style="background-color:#EEE"| <tex>\bf{unknown}</tex>
 
!style="background-color:#EEE"| <tex>\bf{false}</tex>
 
!style="background-color:#EEE"| <tex>\bf{false}</tex>
 
|-
 
|-
|style="background-color:#EEE;color:#00F;;padding:2px 30px"| <tex>\bf{is\ true}</tex>
+
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{true}</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
+
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 
|-
 
|-
|style="background-color:#EEE;color:#00F;;padding:2px 30px"| <tex>\bf{is\ unknown}</tex>
+
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{unknown}</tex>
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
+
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 +
|style="background-color:#FFF;padding:2px 30px"| <tex>unknown</tex>
 
|-
 
|-
|style="background-color:#EEE;color:#00F;;padding:2px 30px"| <tex>\bf{is\ false}</tex>
+
|style="background-color:#EEE;padding:2px 30px"| <tex>\bf{false}</tex>
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
|-
 
|style="background-color:#EEE;color:#00F;;padding:2px 30px"| <tex>\bf{is\ not\ true}</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
|-
 
|style="background-color:#EEE;color:#00F;;padding:2px 30px"| <tex>\bf{is\ not\ unknown}</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|-
 
|style="background-color:#EEE;color:#00F;;padding:2px 30px"| <tex>\bf{is\ not\ false}</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>true</tex>
 
|style="background-color:#FFF;padding:2px 30px"| <tex>false</tex>
 
 
|}
 
|}
==== Скалярные операции ====
+
Оказывается что законы Де Моргана в данном случае '''не работают'''.
Чтобы работа с '''null''' не приводила к непреднамеренным ошибкам полезно знать, что '''null''' "заразен".<br>
+
 
Например, следующие операции с '''null''' порождают '''null'''  
+
=== Скалярные операции, порождающие null ===
 +
Следующие операции с '''null''' порождают '''null''', и иногда это может сбивать с толку начинающих разработчиков.
 
* =, <>, <, <=, >, >=
 
* =, <>, <, <=, >, >=
 
* +, −, *, /
 
* +, −, *, /
 
* ||
 
* ||
* in ('''''in'''(true, false, null)'' не дает нужного эффекта, т.к. сравнение с '''null''' попродит '''null''')
+
* in
 +
Рассмотрим несколько примеров.
 +
* <font color = blue>select</font> (1 + <font color = blue>null</font>) <font color = blue>from</font> Students;
 +
Не смотря на то, что этот запрос не несет большого смысла, на его примере можно убедиться, что в арифместических операциях '''null''' "заразен".
 +
 
 +
* <font color = blue>select</font> StudentId <font color = blue>from</font> Students where GroupId = null;
 +
Это частая ошибка, сравнение с '''''null''''' дает ''unknown'', а значит запрос вернет пустую таблицу.
 +
 
 +
=== Дубликаты и null ===
 +
Так как null ≠ null, сравнения кортежей, содержащих null не обладают интуитивными свойствами, например:
 +
* <tex>$R$ \cup $R$</tex> - не всегда <tex>$R$</tex>
 +
* <tex>$R$ \cap $R$</tex> - не всегда <tex>$R$</tex>
 +
* <tex>$R$ \Bowtie $R$</tex> - не всегда <tex>$R$</tex>
 +
 
  
 
===== coalesce(v1, v2, ...) =====
 
===== coalesce(v1, v2, ...) =====
Строка 207: Строка 219:
 
* Если все аргументы null - возвращает '''null'''
 
* Если все аргументы null - возвращает '''null'''
  
=== Дубликаты и null ===
+
 
Так как null ≠ null, сравнения кортежей, содержащих null не обладают интуитивными свойствами, например:
 
* ''R ∪ R'' - не всегда R
 
* ''R ∩ R'' - не всегда R
 
* ''R ⋈ R'' - не всегда R
 
  
 
=== Спецэффекты ===
 
=== Спецэффекты ===
Строка 240: Строка 248:
 
Из-за наличия '''null''', этот запрос не отработает так, как предполагалось.
 
Из-за наличия '''null''', этот запрос не отработает так, как предполагалось.
  
== Null и SQL ==
+
== Работа с null в SQL ==
 
=== Предикаты ===
 
=== Предикаты ===
 
==== DML ====
 
==== DML ====

Версия 02:35, 23 декабря 2021

Эта статья находится в разработке!

Что означает null

Представим себе таблицы в БД университета ИТМО

  • Students(StudentId, StudentName, GroupId)
  • Groups(GroupId, GroupName)

Что может означать тот факт, что у студента null в столбце GroupId?

  • Значение неизвестно (нет информации, из какой группы студент)
  • Значение неверно (студент учится в какой-то группе, но эта группа не представлена в БД)
  • Значение еще/уже не существует (студент был зачислен, но еще не распределен в группу или уже отчислен)
  • Значение не имеет смысла (студент из другого университета, который пришел с какими-то целями в ИТМО)
  • Значение недоступно (недостаточно прав узнать группу)

На основе этих предположений можно сделать вывод, что значение null сильно зависит от контекста (какую предметную область мы моделируем итд.).
Вполне возможно, что возникнет необходимость различать разные виды того, что значение в том или ином смысле отсутствует.

Можно ли обойтись без null?

Как представить кортеж с неопределенными частями в нашем случае?

  • Разбить на 2 группы и сделать необязательную связь 1:1. В таком случае, в дополнительной таблице будет запись (StudentId, GroupId) тогда и только тогда, когда у студента определена группа

Где еще появляется null

  • Результаты внешних соединений
  • Результаты множественных операций

Оказывается, что в некоторых случаях без null не обойтись и надо уметь с ним работать.

Тернарная логика с использованием null

С точки зрения SQL, результат логического выражения может быть true, false или unknown.
С другой стороны есть тип boolean, и у него есть 3 значения: true, false и null
То есть формально unknown - это результат вычисления, а null - это конкретное значение, которое может быть записано в БД. На практике unknown представляется значением null, и это различие не будет иметь большого значения.

Конъюнкция

[math]\bf{and}[/math] [math]\bf{true}[/math] [math]\bf{unknown}[/math] [math]\bf{false}[/math]
[math]\bf{true}[/math] [math]true[/math] [math]unknown[/math] [math]false[/math]
[math]\bf{unknown}[/math] [math]unknown[/math] [math]unknown[/math] [math]false[/math]
[math]\bf{false}[/math] [math]false[/math] [math]false[/math] [math]false[/math]

Дизъюнкция

[math]\bf{or}[/math] [math]\bf{true}[/math] [math]\bf{unknown}[/math] [math]\bf{false}[/math]
[math]\bf{true}[/math] [math]true[/math] [math]true[/math] [math]true[/math]
[math]\bf{unknown}[/math] [math]true[/math] [math]unknown[/math] [math]unknown[/math]
[math]\bf{false}[/math] [math]true[/math] [math]unknown[/math] [math]false[/math]

Отрицание

[math][/math] [math]\bf{true}[/math] [math]\bf{unknown}[/math] [math]\bf{false}[/math]
[math]\bf{not}[/math] [math]false[/math] [math]unknown[/math] [math]true[/math]

Сравнение

=

[math]\bf{=}[/math] [math]\bf{true}[/math] [math]\bf{unknown}[/math] [math]\bf{false}[/math]
[math]\bf{true}[/math] [math]true[/math] [math]unknown[/math] [math]false[/math]
[math]\bf{unknown}[/math] [math]unknown[/math] [math]unknown[/math] [math]unknown[/math]
[math]\bf{false}[/math] [math]false[/math] [math]unknown[/math] [math]true[/math]

is

[math][/math] [math]\bf{true}[/math] [math]\bf{unknown}[/math] [math]\bf{false}[/math]
[math]\bf{is\ true}[/math] [math]true[/math] [math]false[/math] [math]false[/math]
[math]\bf{is\ unknown}[/math] [math]false[/math] [math]true[/math] [math]false[/math]
[math]\bf{is\ false}[/math] [math]false[/math] [math]false[/math] [math]true[/math]
[math]\bf{is\ not\ true}[/math] [math]false[/math] [math]true[/math] [math]true[/math]
[math]\bf{is\ not\ unknown}[/math] [math]true[/math] [math]false[/math] [math]true[/math]
[math]\bf{is\ not\ false}[/math] [math]true[/math] [math]true[/math] [math]false[/math]

Проблемы при работе с null

При работе с null в процессе разработки БД, во избежание непредвиденных ошибок, необъодимо заранее ознакомиться с тем, какие проблемы могут возникнуть.

Неоднозначность импликации

TODO: уточнить

  • A → B = (not A) or B
[math]\bf{(not\ A)\ or\ B}[/math] [math]\bf{true}[/math] [math]\bf{unknown}[/math] [math]\bf{false}[/math]
[math]\bf{true}[/math] [math]true[/math] [math]unknown[/math] [math]false[/math]
[math]\bf{unknown}[/math] [math]true[/math] [math]unknown[/math] [math]unknown[/math]
[math]\bf{false}[/math] [math]true[/math] [math]true[/math] [math]true[/math]
  • A → B = not (A and not B)
[math]\bf{not\ (A\ and\ not\ B)}[/math] [math]\bf{true}[/math] [math]\bf{unknown}[/math] [math]\bf{false}[/math]
[math]\bf{true}[/math] [math]true[/math] [math]unknown[/math] [math]false[/math]
[math]\bf{unknown}[/math] [math]true[/math] [math]unknown[/math] [math]unknown[/math]
[math]\bf{false}[/math] [math]true[/math] [math]true[/math] [math]true[/math]

Оказывается что законы Де Моргана в данном случае не работают.

Скалярные операции, порождающие null

Следующие операции с null порождают null, и иногда это может сбивать с толку начинающих разработчиков.

  • =, <>, <, <=, >, >=
  • +, −, *, /
  • ||
  • in

Рассмотрим несколько примеров.

  • select (1 + null) from Students;

Не смотря на то, что этот запрос не несет большого смысла, на его примере можно убедиться, что в арифместических операциях null "заразен".

  • select StudentId from Students where GroupId = null;

Это частая ошибка, сравнение с null дает unknown, а значит запрос вернет пустую таблицу.

Дубликаты и null

Так как null ≠ null, сравнения кортежей, содержащих null не обладают интуитивными свойствами, например:

  • [math]$R$ \cup $R$[/math] - не всегда [math]$R$[/math]
  • [math]$R$ \cap $R$[/math] - не всегда [math]$R$[/math]
  • [math]$R$ \Bowtie $R$[/math] - не всегда [math]$R$[/math]


coalesce(v1, v2, ...)
  • Принимает произвольное число аргументов и возвращает первый не null
  • Если все аргументы null - возвращает null


Спецэффекты

При детальном рассмотрении, оказывается, что сравнение не транзитивно и не рефлексивно.

  • x = x - true или null
  • x <> x - true или null
  • x or x - true или null
  • x or not x - true или null
  • x and not x - false или null

Ключи и null

Можно использовать null:

  • Альтернативные ключи
  • Внешние ключи
    • Простые
    • Составные, отсутствующие целиком

Первичные ключи не могут содержать null.

Неинтуитивность null

Студенты, учащиеся в группе M34391

select * from Students where GroupId <> 'M34391'

Корректность запроса зависит от смысла null. Неясно, надо ли возвращать в этом запросе студента, о котором нет информации, в какой группе он учится.

Поиск всех студентов

select * from Students where GroupId <> 'M34391'
union
select * from Students where GroupId <> 'M34391'

Из-за наличия null, этот запрос не отработает так, как предполагалось.

Работа с null в SQL

Предикаты

DML

where и having считают истинным предикат только если он вернул true

DDL

C точки зрения check constraint-ов не подходит только false. Unknown превращается в true

Различимость

Два null не равны и не различимы. Это важно для distinct и group by
Например, кортежи (1, null) и (1, null) склеятся в случае distinct и не породят разные группы в случае group by, т.к. не различимы

Типы столбцов

  • nullable (по умолчанию)
    • birthday date
  • Не nullable
    • birthday date not null

Проверки значений

Синтаксис

  • значение is [not] {null|true|false|unknown}

Примеры

  • x is null
  • x is not true
  • (x or x) is not null

Прочее

exists, Агрегирующие функции, Order by