До этого момента разговор о типах данных PostgreSQL велся в общих словах (см. вот этот мой блог). Из схемы видно, что использованные типы (далеко не все из имеющихся в PostgreSQL) - это скорее базовые типы, известные средству проектирования, которые могут быть преобразованы в реальные типы данных PostgreSQL при создании реальных таблиц.
Перед нами осталось еще одно препятствие, преодолением которого мы пока не занимались, - генерирование уникальных ключей таких полей, как customer_id
и item_id
. Вы, конечно же, помните, что каждая строка таблицы должна быть однозначно идентифицируемой и что в тех случаях, когда нет очевидного набора столбцов, который мог быть использоваться для достижения этой цели, добавляется дополнительный столбец, столбец с уникальным идентификатором. На ум приходит поле целых чисел или символьное поле, при этом, добавляя каждую новую строку, необходимо генерировать новое уникальное значение для столбца.
Поскольку необходимость введения дополнительного уникального столбца встречается при проектировании баз данных повсеместно, существует и встроенное решение, новый тип данных SERIAL
. Этот специальный тип представляет собой целое число, автоматически увеличивающееся при добавлении строки в таблицу и устанавливающее новое уникальное значение при добавлении каждой строки. Если новая строка вводится в таблицу, имеющую столбец типа SERIAL
, не нужно указывать никакого значения для этого столбца, СУБД сама автоматически присвоит следующее значение.
В большинстве баз данных при присваивании последовательных величин удаленные строки не учитываются. Присваиваемое число просто увеличивается для каждой новой строки. Средство проектирования, с помощью которого были выполнены представленные выше диаграммы, показывает поля типа SERIAL
как INTEGER
, потому что этот тип является базовым.
Тип данных | Описание |
| Целое число. |
| Целое число, автоматически устанавливаемое в уникальную величину для каждой добавляемой строки. На рисунках это не отражено, но именно этот тип будет использоваться для столбцов «_id». |
| Символьный массив фиксированного размера, размер указывается в скобках после названия типа. В столбцах данного типа PostgreSQL всегда будет сохранять ровно указанное количество символов. Если CHAR(256) служит для хранения одного символа, в базе данных будет занято как минимум 256 байт, которые и будут возвращены при извлечении данных. |
| Это также символьный массив, но (как понятно из названия) переменной длины, и обычно место, занимаемое в базе данных, практически совпадает с фактическим размером сохраняемых данных. При обращении к полю |
| Позволяет хранить данные о годе, месяце и дне. Конечно же, есть и другие родственные типы, позволяющие хранить данные о времени (вместе с информацией о дате или без). Вернемся к этому позже. |
| Возможность хранить числа с указанным количеством разрядов (первое число в скобках) и фиксированным количеством разрядов после запятой (второе число в скобках). Так, |
Далее в моем блоге будут рассмотрены и другие типы данных PostgreSQL, при этом окажется, что какие-то из них больше подходят для хранения денежных значений, чем NUMERIC
, поскольку несмотря на то, что использовать NUMERIC весьма удобно, это не самый эффективный способ хранения чисел с плавающей запятой в PostgreSQL.
Значение NULL
Новичков в теории баз данных может смутить такое понятие, как NULL
. В терминах баз данных NULL
обычно означает, что величина не известна (хотя существуют еще одна-две разновидности определения с едва уловимыми отличиями).
Посмотрим на таблицу orderinfo, в ней содержится столбец дат заказа, а также столбец дат отгрузки, оба имеют тип DATE
. Как следует поступить, если заказ уже получен, но еще не отправлен? Что сохранить в столбце дат отгрузки? Можно сохранить специальную дату, сигнальную величину (sentinel value), которая указывала бы, что заказ еще не отправлен. В системах UNIX можно использовать в качестве такой даты 1 января 1970 года, т. к. именно с этого дня системы UNIX ведут свой отсчет. В любом случае эта дата должна предшествовать дате создания базы данных, тогда будет очевидно, что дата специальная, в нашем же случае она будет иметь смысл «еще не отправлено».
Понятно, что такое решение далеко от идеала. Наличие специальных величин, разбросанных по таблицам, свидетельствует о неудачности проекта и часто приводит к ошибкам. Например, если к работе над проектом подключается новый программист, который не знает о присутствии специальных дат, он может заняться подсчетом того, сколько времени в среднем проходит между размещением заказа и его отгрузкой, и получить весьма неожиданные результаты (если в нескольких случаях даты отправления были установлены как предшествующие дате размещения заказа).
К счастью, во всех реляционных базах данных существует специальная величина под названием NULL
, которая обычно означает «в настоящий момент неизвестно». Обратите внимание, что это не ноль, не пустая строка и не нечто, что могло бы быть представлено в поле некоторого типа. «Неизвестное» очень сильно отличается от 0 и пустой строки.
Чрезвычайно важно присматривать за такими величинами, потому что они могут появляться в произвольных местах, причиняя неудобства. В таблице orderinfo
можно установить дату отправки в NULL
(до того, как заказ отгружен), значение «в настоящий момент неизвестно» полностью соответствует нашей ситуации.
Существует и несколько другое значение NULL
(оно не так распространено, как первое) - «не относится» (not relevant) к данной строке. Предположим, например, что проводится опрос группы людей, при этом один из вопросов касается цвета очков. Но для тех, кто очки не носит, этот вопрос, естественно, не имеет никакого смысла. В таком случае можно использовать NULL
в соответствующем столбце, для того чтобы показать, что информация не имеет отношения к данной конкретной строке.
Проверка на NULL
Одним из свойств NULL
является следующее: при сравнении двух значений NULL
результатом всегда будет «не равны». Это может удивить, но подумайте, ведь NULL
- это неизвестное, поэтому абсолютно логично, что при сравнении двух неизвестных оказывается, что они не равны.
В SQL предоставлена специальная возможность проверки величин на значение NULL, если необходимо найти их и проверить, то задается вопрос 'IS NULL'.
Поведение величин NULL может иметь свои особенности, поэтому при проектировании таблицы можно указать, что в некоторых столбцах не могут храниться NULL. Обычно удобно бывает сказать, что для столбцов будет выполняться условие NOT NULL', - для уверенности в том, что NULL там не появится (например, в столбце, представляющем собой первичный ключ). Некоторые проектировщики баз данных пропагандируют практически полную отмену использования величин NULL, но все же в них есть и определенная польза. Поэтому, как правило, поддерживается применение величин NULL в отдельных столбцах при наличии реальной потребности в значениях, которые не определены.