Что такое PostgreSQL?
Бесплатная версия
Проект PostgreSQL распространяется на условиях открытых исходных текстов. Это означает, что пользователь может взять исходный текст программы, использовать его и свободно модифицировать без ограничений, устанавливаемых для закрытых программных продуктов. В области баз данных открытость исходных текстов означает, что пользователь получает полный доступ к данным эталонных тестов и статистике быстродействия, недоступным в продуктах некоторых компаний (например, Oracle). Кроме того, открытость исходных текстов позволяет потребителю модифицировать PostgreSQL для своих конкретных целей.
Тем не менее не следует полагать, что программы, распространяемые с открытыми исходными текстами, ничего не стоят конечному пользователю. Действительно, за загрузку и установку программного продукта платить не придется, но всегда приходится учитывать время и усилия, затрачиваемые на изучение пакета и дальнейшее сопровождение. Если ваша компания не располагает соответствующими ресурсами, воспользуйтесь услугами коммерческих организаций и консультантов, занимающихся PostgreSQL.
Что дальше?
Что дальше?
После краткого знакомства с PostgreSQL перед читателем открывается несколько путей. Следующий список дает примерное представление о содержимом книги. Этот «путеводитель» поможет вам самостоятельно решить, о чем читать дальше.
- Если вы хотите заняться установкой PostgreSQL 7.1.x, переходите к главе 2.
- Если у вас нет опыта работы с языком SQL и запросами к базам данных, продолжайте чтение с главы 3. Хотя материал главы 3 в основном носит общий характер, в ней также описаны некоторые приемы и концепции, характерные только для PostgreSQL. Обратите на них особое внимание, если хотите досконально разобраться в программе.
- Если вы уже знакомы с языком SQL и структурой команд, вероятно, вас больше заинтересуют главы 4, 5 и 7.
- Если вы владеете практическими навыками работы с PostgreSQL в качестве конечного пользователя и хотите перейти к настройке сервера, определению пользователей и групп, а также заданию параметров аутентификации, переходите к части III. Эта часть призвана помочь системным администраторам в инициализации, настройке и управлении вновь созданными или существующими базами данных PostgreSQL.
- Если вы знакомы с СУБД PostgreSQL и интересуетесь техническими сторонами и методикой программирования, переходите к части IV. В этой части книги описан PL/pgSQL, «родной» процедурный язык PostgreSQL, а также интерфейс JDBC и сервер приложений LXP на базе Web.
Что такое PostgreSQL?
Что такое PostgreSQL?
PostgreSQL - - объектно-реляционная система управления базами данных (ОРСУБД), разработка которой в различных формах ведется с 1977 года. Работа началась с проекта Ingres в Калифорнийском университете (Беркли). Затем проект Ingres был переведен на коммерческую разработку в корпорации Relational Technologies/Ingres.
В 1986 году другая группа, которую возглавлял Майкл-Стоунбрейкер (Michael Stonebraker) из Беркли, продолжила работу над Ingres и создала объектно-реляционную СУБД Postgres. В 1996 году из-за усовершенствования пакета и перехода на распространение с открытыми исходными текстами было принято новое название — PostgreSQL (в течение непродолжительного времени использовалось название Postgres95). В настоящее время над проектом PostgreSQL активно работает группа разработчиков со всего мира.
PostgreSQL считается самой совершенной СУБД, распространяемой на условиях открытых исходных текстов. В PostgreSQL реализованы многие возможности, традиционно встречавшиеся только в масштабных коммерческих продуктах (за дополнительной информацией обращайтесь к разделу «Возможности PostgreSQL»).
Коммерческие продукты семейства PostgreSQL
Коммерческие продукты семейства PostgreSQL
Версия PostgreSQL для операционной системы Red Hat называется «Red Hat Database». Этот продукт относительно недавно появился на рынке баз данных. В основу Red Hat Database заложена версия с открытыми текстами PostgreSQL 7.1. В настоящее время Red Hat Database работает только в системе Linux, желательно в Red Hat Linux 7.1.
Поддержка сообщества PostgreSQL
Поддержка сообщества PostgreSQL
Сообщество PostgreSQL обеспечивает активную поддержку продукта через списки рассылки. Существует несколько списков рассылки, на которые вы можете подписаться, разделенные по темам (например, pfsql-general, pgsql-hackers и т. д.). Списки
рассылки для пользователей SQL содержат достаточно подробную информацию от общих вопросов до разработки программных интерфейсов PostgreSQL. Полный перечень списков рассылки с подробными описаниями приведен на сайте http:/ /www. postg resql.org.
Продукты бесплатные и коммерческие
Продукты бесплатные и коммерческие
Бесплатная версия PostgreSQL состоит только из системы управления базами данных и программных интерфейсов. Версия PostgreSQL для Red Hat также включает графическую программу установки и ограниченную техническую поддержку.
Выбор между коммерческой и бесплатной версиями PostgreSQL определяется прежде всего деловыми соображениями. При наличии компетентного технического персонала вполне подойдет и бесплатная версия, но если вам потребуется поддержка в процессе установки, настройки и администрирования, возможно, лучше приобрести коммерческую версию PostgreSQL.
Возможности PostgreSQL
Возможности PostgreSQL
Как упоминалось выше, PostgreSQL считается самой совершенной СУБД, распространяемой на условиях открытых исходных текстов. В PostgreSQL реализованы многие возможности, обычно присутствующие только в коммерческих СУБД, таких как DB2 и Oracle. Ниже перечислены основные возможности PostgreSQL версии 7.1.x.
- Объектно-реляционная модель. Работа с данными в PostgreSQL основана на объектно-реляционной модели, что позволяет задействовать сложные процедуры и системы правил. Примерами нетривиальных возможностей этой категории являются декларативные запросы SQL, контроль параллельного доступа, поддержка многопользовательского доступа, транзакции, оптимизация запросов, поддержка наследования и массивов.
- Простота расширения. В PostgreSQL поддерживаются пользовательские операторы, функции, методы доступа и типы данных.
- Полноцепная поддержка SQL. PostgreSQL соответствует базовой спецификации SQL99 и поддерживает такие нетривиальные средства, как объединения стандарта SQL92.
- Проверка целостности ссылок. PostgreSQL поддерживает проверку целостности ссылок, обеспечивающую правильность данных в базе.
- Гибкость API. Гибкость API PostgreSQL позволяет легко создавать интерфейсы к РСУБД PostgreSQL. В настоящее время существуют программные интерфейсы для Object Pascal, Python, Perl, PHP, ODBC, Java/JDBC, Ruby, TCL, C/ C+ и Pike.
- Процедурные языки. В PostgreSQL предусмотрена поддержка внутренних процедурных языков, в том числе специализированного языка PL/pgSQL, являющегося аналогом PL/SQL, процедурного языка Oracle. Одним из преимуществ PostgreSQL является возможность использования Perl, Python и TCL в качестве внутренних процедурных языков.
- МУСС. Технология MVCC (Multi-Version Concurrency Control) используется в PostgreSQL для предотвращения лишних блокировок (locking). Каждый, кто хоть раз работал с другими СУБД на базе SQL (например, MySQL или Access), наверняка замечал, что обращение к базе данных для чтения иногда сопровождается задержками, связанными с попытками записи в базу данных. Проще говоря, операции чтения блокируются операциями, производящими обновление записей. Применение технологии MVCC в PostgreSQL полностью решает эту проблему. MVCC лучше низкоуровневой блокировки, поскольку операции чтения никогда не блокируются операциями записи. Вместо этого PostgreSQL отслеживает все транзакции, выполняемые пользователями базы данных, что позволяет работать с записями без ожидания их освобождения.
Опережающая регистрация изменений. Опережающая регистрация изменений (Write Ahead Logging, WAL) повышает надежность данных. Все изменения данных протоколируются до их непосредственной актуализации в базе. Наличие протокола изменений гарантирует, что в случае сбоя базы данных (что весьма маловероятно) данные можно будет восстановить по запротоколированным транзакциям. После восстановления системы пользователь продолжает работу с состояния, непосредственно предшествовавшего сбою.
Из сказанного может возникнуть впечатление,
Выводы
Из сказанного может возникнуть впечатление, что коммерческая версия PostgreSQL в чем-то объективно лучше бесплатной версии. В действительности это не так. При выборе версии необходимо руководствоваться только требованиями конкретной ситуации. Потребуется ли техническая поддержка на стадии установки? Так ли необходима графическая оболочка в программе установки? Если на оба вопроса вы ответили положительно, подумайте о приобретении коммерческой версии PostgreSQL. Но если вы или технические специалисты вашей организации справятся с компиляцией исходных текстов и изменением конфигурации, возможно, бесплатная версия окажется более подходящей.
Также следует ответить на два дополнительных вопроса. Нужна ли вам печатная документация? Готовы ли вы заплатить за PostgreSQL? Печатная документация входит в комплект поставки коммерческой версии, но авторы надеются, что после чтения этой книги дополнительная документация вам уже не понадобится. Также приходится учитывать и цену коммерческой версии: Red Hat Database стоит 2295 долларов.
Главное, о чем следует помнить при выборе версии PostgreSQL (с позиций общей полезности и широты возможностей), — между бесплатной и коммерческой версиями не существует функциональных различий.
Краткий курс SQL
Анатомия команд SQL
Анатомия команд SQL
Команды SQL всегда начинаются с действия (verb) — слова или группы слов, описывающих выполняемую операцию. Кроме того, команда SQL обычно содержит одну или несколько секций, уточняющих ее смысл. В табл. 3.2 перечислены основные действия SQL.
Базы данных
Базы данных
Хотя РСУБД PostgreSQL часто называют просто «базой данных», этот термин часто приводит к недоразумениям. База данных PostgreSQL представляет собой объектно-реляционную реализацию того, что в стандарте SQL99 формально называется схемой (schema).
Проще говоря, базой данных называется совокупность логически связанных данных, хранящихся вместе. Обычно СУБД обеспечивает доступ к этим данным в многопользовательской среде. В PostgreSQL дело обстоит именно так, хотя доступ ограничивается системой четко определенных прав и ограничений.
PostgreSQL может одновременно предоставлять доступ к нескольким базам данных, у каждой из которых имеется свой владелец, свои таблицы, представления, индексы и функции.
Чтобы создать таблицу, функцию или любой другой объект базы данных, вы подключаетесь к конкретной базе данных при помощи клиента PostgreSQL. После подключения создается объект, принадлежащий этой базе данных и недоступный для всех остальных баз данных (хотя клиент может одновременно открыть несколько подключений к разным базам).
Жесткая изоляция основных объектов данных в базах данных снижает опасность возникновения конфликтов имен при выборе имени, ранее зарезервированного для другой цели (например, если два пользователя захотят создать таблицу с именем products для двух разных целей). Это связано с тем, что ни одна база данных не располагает информацией о компонентах других баз и не пытается устанавливать с ними какие-либо логические связи. Более того, это правило распространяется и на объекты данных объектно-реляционных баз, поэтому созданные пользователем функции и языковые определения недоступны для других пользователей, подключающихся к другим базам данных через PostgreSQL.
По умолчанию PostgreSQL создает только одну рабочую базу данных с именем template 1. Любая база данных, созданная после template 1, фактически является ее клоном и наследует от прототипа все характеристики и объекты, включая структуру таблиц, функции, языки и т. д. Для новых пользователей PostgreSQL нередко создается стандартная база данных с именем, соответствующим имени пользователя PostgreSQL, поскольку если при подключении пользователя имя базы данных не указано, PostgreSQL по умолчанию в качестве имени базы данных подставляет имя пользователя.
Битовые последовательности
Битовые последовательности
Битовые последовательности предназначены для представления двоичных величин в виде произвольной последовательности нулей и единиц. Как и строковые константы, битовые последовательности заключаются в апострофы, но начинаются с обязательного префикса В (в верхнем или нижнем регистре). По наличию этого символа PostgreSQL определяет, что строка является битовой последовательностью, а не обычной символьной строкой.
В соответствии с синтаксисом PostgreSQL открывающий апостроф должен следовать сразу же после префикса В, а битовая последовательность не может содержать других символов, кроме 0 и 1. Внутренние пробелы в битовых последовательностях запрещены, но допускается их разбиение по аналогии с обычными строковыми константами (см. выше пункт «Строковые константы).
Битовые строки обычно требуются только при работе с двоичными функциями и таблицами, содержащими двоичные данные. В листинге 3.6 продемонстрирована вставка битовой последовательности в таблицу. Сначала двоичное представление байта сохраняется в таблице my_bytes, а затем результат операции проверяется простым запросом.
Целочисленные константы
Целочисленные константы
Целочисленные константы используются гораздо чаще, чем битовые последовательности. В PostgreSQL целочисленной константой считается любая лексема, состоящая из цифр (без десятичной точки) и не заключенная в апострофы. Интервал допустимых значений целочисленных констант зависит в основном от контекста, но в PostgreSQL по умолчанию целочисленный тип представляется четырьмя байтами и принимает значения из интервала от -2 147 483 648 до 2 147 483 647.
Целочисленные константы часто встречаются в математических операциях, а также в командах SQL, содержащих ссылки на поля целочисленного типа. В листинге 3.7 целочисленные константы используются для обновления кода автора командой UPDATE.
Вспомните таблицу authors, которая устанавливает соответствие между числовым кодом автора и двумя строками, представляющими его имя и фамилию. Допустим, из каких-то административных соображений было решено, что все коды авторов, меньшие 100, нужно увеличить до 100 и выше.
Внесение исправлений начинается с поиска записей, у которых поле id удовлетворяет данному условию. Для этого в команду SELECT включается секция WHERE с целочисленной константой, используемой при проверке условия «меньше».
Числовые типы
Числовые типы
Числовые типы PostgreSQL используются для представления целых и вещественных значений. С общей точки зрения к числовым типам PostgreSQL относятся следующие типы:
- 2-, 4- и 8-байтовые целые числа;
- 4- и 8-байтовые вещественные числа;
- дробные числа с фиксированной точностью.
Дата и время
Дата и время
Следующая категория типов является удобным средством для хранения даты и времени в универсальной структуре SQL. При этом программист избавляется от хлопот, связанных с форматом хранения (как, например, при хранении этих данных в символьных строках). В PostgreSQL все вычисления с датой и временем производятся но юлианскому календарю. Продолжительность года считается равной 365,24 дня, что обеспечивает правильное представление любой даты с 4713 года до нашей эры и далеко в будущее.
В PostgreSQL поддерживаются все типы даты и времени, определенные в стандарте SQL92 (табл. 3.14), а также некоторые вспомогательные типы PostgreSQL, помогающие решить проблемы с представлением часовых поясов в SQL92.
Формат представления даты
Формат представления даты
В PostgreSQL предусмотрено несколько стандартных форматов даты, в том числе формат ISO-8601, традиционный формат SQL, исходный формат PostgreSQL и многие другие. Некоторые форматы даты указаны в табл. 3.15.
Перечисленные форматы относятся к типам данных date и timestamp.
Форматирование команд SQL
Форматирование команд SQL
Как упоминалось в предыдущем подразделе, команды SQL состоят из последовательности элементов — лексем. Менее очевиден тот факт, что лексемы могут находиться в одной или нескольких строках, поскольку модуль лексического разбора PostgreSQL игнорирует лишние пропуски (в том числе разрывы строк).
В листинге 3.1 приведена команда SQL, которая в первом случае задана в одной строке, а во втором повторяется с разбивкой на несколько строк. Оба варианта команды SELECT выводят все содержимое таблицы my_list.
Форматы представления времени
Форматы представления времени
Время, как и дата, может задаваться разными способами. В табл. 3.20 перечислены самые распространенные форматы значений типов time и time with time zone.
Геометрические типы
Геометрические типы
Геометрические типы PostgreSQL предназначены для представления объектов на плоскости. Они не относятся к стандартным типам данных SQL и потому в книге подробно не рассматриваются. В табл. 3.24 приведена краткая сводка поддерживаемых геометрических типов.
Идентификаторы объектов
Идентификаторы объектов
Как было сказано в подразделе «Таблицы» раздела «Знакомство с реляционными базами данных», база данных содержит таблицы, а каждая таблица содержит хотя бы одно именованное поле. Таблица может содержать записи данных, но их наличие не является обязательным. Каждое поле записи, хранящейся в таблице, содержит некоторые данные или NULL.
Один из вопросов, которые приходится решать при операциях с базами данных, — как различить две записи с одинаковыми значениями полей? Для этого в PostgreSQL предусмотрены идентификаторы объектов (object identifiers, OID), никальные в пределах таблицы. Иначе говоря, таблица никогда не содержит записи одинаковыми идентификаторами OID. Таким образом, даже если содержимое пользовательских полей двух записей полностью совпадает, на программном уровне записи можно различить по значению OID. Пример приведен в листинге 3.31.
Интервальный тип
Интервальный тип
В стандарте SQL92 определен тип данных interval, представляющий фиксированный промежуток времени. Сам по себе тип interval представляет лишь количественную величину, не связанную с определенным начальным или конечным моментом. Интервалы часто используются в сочетании с типами даты и времени для вычисления новой величины посредством сложения или вычитания. Кроме
того, они могут пригодиться для быстрого вычисления точного промежутка между двумя датами или моментами времени, для чего одна величина вычитается из другой.
В PostgreSQL поддерживаются два варианта синтаксиса определения интервалов:
длина единице [ago]
длина! единица [. длина2 единица2 ... ]
[ago]
Здесь:
- длина — продолжительность интервала, заданная в виде целого или вещественного (для микросекунд) числа. Интерпретация числа определяется следующим параметром.
- единица — единица, в которой измеряется заданный интервал. Разрешены следующие ключевые слова: second, minute, hour, day, week, month,year, decade, century, millennium. Также допускаются сокращения (любой длины при условии однозначной интерпретации) и формы множественного числа.
- ago — необязательное ключевое слово ago указывает, что описываемый период времени предшествует некоторому моменту, а не следует после него. Ключевое слово ago можно рассматривать как аналог знака минус (-) в типах даты и времени.
Язык SQL и его предшественники
Язык SQL и его предшественники
Язык SQL в значительной степени основан на реляционной алгебре и кортежно-реляционной модели. Реляционная алгебра, представленная Э. Ф. Коддомв 1972 году, определяет базовые принципы обработки синтаксиса SQL; это процедурный способ построения запросов, управляемых данными, который определяет способ достижения поставленной цели. С другой стороны, кортежно-реляционная модель использует декларативные выражения и определяет саму цель при обработке структурированных запросов.
Некоторые перечисленные ниже дополнительные возможности отделяют язык SQL от его предшественников, ограничивающихся простой реализацией отдельных аспектов реляционной алгебры или модели.
- Поддержка вставки, модификации и удаления данных. Пользователям разрешается вставлять, удалять и обновлять записи, хранящиеся в базе данных.
- Математические операторы. В SQL используются математические операторы сложения, вычитания, умножения, деления, а также выражения вида (valuel * 5) + valueZ. Также поддерживаются операторы сравнения (например, values >= value4).
- Отображение данных. Пользователь может вывести связи, сгенерированные при обработке запроса.
- Присваивание. Пользователь может переименовать связь, сгенерированную при обработке запроса. Он не ограничен стандартным именем связи, производным от имени поля или функции (в зависимости от запроса).
- Агрегатные функции. Пользователь может группировать логически связанные записи и вычислять сводные показатели (среднее арифметическое, сумму, количество, максимальное или минимальное значение).
Ключевые слова и идентификаторы
Ключевые слова и идентификаторы
Ключевыми словами называются зарезервированные термины SQL, имеющие особый синтаксический смысл для сервера (INSERT, UPDATE, SELECT, DELETE и т. д.).
Каждая команда SQL начинается с ключевого слова, хотя многие ключевые слова сами по себе не являются законченными командами. Например, конструкция INSERT INTO является действительной командой SQL, а слово INTO является зарезервированным ключевым словом. Но как нетрудно предположить, слово INTO не имеет смысла вне контекста.
Идентификаторы, как упоминалось выше, представляют собой имена переменных для ссылки на объекты базы данных. Имена идентификаторов произвольно назначаются при создании базы данных. В PostgreSQL идентификаторы могут связываться с базами данных, таблицами, полями, индексами, представлениями, последовательностями, правилами, триггерами и функциями.
В листинге 3.2 в простую таблицу states включается запись, состоящая из трех полей.
Команды SQL
Команды SQL
Любая концептуальная информация о реляционных базах данных и таблицах приносит пользу лишь в том случае, если вы знаете, как организовать взаимодействие с данными. Язык SQL состоит из структурированных команд, предназначенных для добавления, модификации и удаления данных из базы. Эти команды образуют основу для взаимодействия с сервером PostgreSQL
Этот раздел посвящен «анатомии» команд SQL. В нем рассматриваются структурные компоненты команд, описываются функции каждого компонента и их взаимные связи. Стандартный клиент командной строки PostgreSQL, psql, выводит результаты выполнения команд в приведенных примерах.
Большинство примеров команд SQL относится к базе данных booktown. Весь вывод psql снабжается префиксом вида booktown=#
В некоторых примерах используется тестовая база данных testdb. По умолчанию в приглашении psql выводится только имя базы данных и символы =#, означающие, что система готова к вводу новой команды (хотя вы увидите, что символ = динамически изменяется по мере отслеживания состояния входных данных SQL). В книге это приглашение приводится вместе с входными и выходными данными SQL, чтобы вам было проще освоиться с выводом клиента psql.
Клиент psql подробно описан в главе 4. Здесь он упоминается лишь для пояснения стиля примеров команд SQL.
Примечание 1
Примечание 1
Схема базы данных booktown (вместе с примерами записей) находится в файле booktown.sql на компакт-диске. Чтобы установить эту базу данных, введите в приглашении командной строки команду psql -U postgres template! -f /mnt/cdrom/booktown.sql, где /mnt/cdrom — путь к смонтированному компакт-диску, a postgres — имя суперпользователя PostgreSQL.
Комментарием называется
Комментарии
Комментарием называется фрагмент обычного текста, оформленный специальным образом и внедренный в код SQL. Комментарии не влияют на выполнение программы, поскольку PostgreSQL удаляет их из входного потока и интерпретирует как обычные пропуски. Существует две разновидности комментариев: однострочные и многострочные.
Однострочные комментарии начинаются с двух дефисов (- -) и либо находятся в отдельной строке, либо следуют за лексемами SQL (модуль лексического разбора PostgreSQL не считает комментарии лексемами, а все символы, следующие за последовательностью --, интерпретирует как пропуски). Пример однострочного комментария приведен в листинге 3.11.
Константы
Константы
При работе с базами данных многие объекты хранятся на диске, а для обращения к ним используются идентификаторы (имена таблиц, полей и функций). Однако неизбежно настанет момент, когда в систему потребуется передать новые данные — например, при вставке новых записей, при формировании секций с критериями удаления или модификации или при вычислениях на базе существующих записей. Такие данные передаются в виде констант, также иногда называемых «литералами». Константы предназначены для «буквального» представления данных в командах SQL (вместо ссылки на них по идентификатору).
Константы с косвенной типизацией автоматически распознаются модулем лексического разбора PostgreSQL по их синтаксису. В PostgreSQL поддерживаются пять вариатнов констант с косвенной типизацией:
- строковые константы;
- битовые последовательности;
- целочисленные константы;
- вещественные константы;
- логические константы.
Краткая история SQL
Краткая история SQL
В 1970 году доктор Э. Ф. Кодд (Е. F. Codd) из компании IBM в статье «A Relational Model of Data for Large Shared Data Banks» дал формальное определение реляционной модели, образующей концептуальную основу SQL. Данная статья вызвала большой интерес как в плане общей приемлемости, так и в плане практических коммерческих приложений подобных систем.
В 1974 году компания IBM начала работу над проектом System/R. Группа под руководством Дональда Чемберлина (Donald Chamberlin) разработала язык SEQUEL (Structured English Query Language). В 1974-75 годах проект System/R был реализован в прототипе SEQUEL-XRM. Затем в 1976-77 годах проект был полностью переделан, в него была включена поддержка многотабличных и многопользовательских средств. Переработанная система сначала называлась «SEQUEL 2», а затем по соображениям авторских прав была переименована в «SQL».
В 1978 году началось доскональное тестирование системы. Оно наглядно продемонстрировало ее удобство и практическую полезность, в результате чего компания IBM начала разработку коммерческих SQL-продуктов, основанных на прототипе System R, включая SQL/DS (1981 год) и DB2 (1983 год).
Другие разработчики программного обеспечения также обратили внимание на растущую популярность реляционной модели и анонсировали свои продукты на базе SQL. К их числу относились СУБД Oracle, Sybase и Ingres (на базе проекта Ingres Калифорнийского университета в Беркли).
Примечание 1
Примечание 1
Как нетрудно догадаться по названию, СУБД PostgreSQL связана с Ingres. Обе СУБД происходят от проекта Ingres Калифорнийского университета.
Краткий курс SQL
Краткий курс SQL
В этой главе описывается история SQL и основные концепции языка. На базе материала строится следующая глава, посвященная использованию SQL в Post-greSQL. В частности, в ней изложены основные принципы работы реляционных баз данных, описаны объектно-реляционные расширения и структура команд SQL, а также приводится краткий обзор поддерживаемых в PostgreSQL типов данных, операторов и функций.
Пробелы и переводы строк
Листинг 3.1. Пробелы и переводы строк
testdb-* SELECT * FROM mylist;
todos
---------------------------------------
Pick up laundry. Send out bills.
Wrap up Grand Unifying Theory for publication.
(3 rows)
testdb-# SELECT * testdb-* FROM
testdb-# mylist;
todos
--------------------------------------
Pick up laundry. Send out bills.
Wrap up Grand Unifying Theory for publication.
(3 rows)
В листинге 3.1 лексемы второй команды разделены дополнительными пробелами и символами новой строки. Как видно из полученных результатов, PostgreSQL игнорирует лишние пробелы и разрывы строк, вследствие чего команды являются синтаксически эквивалентными. Вы можете воспользоваться этим фактом и разбить длинную команду SQL на несколько строк, чтобы упростить ее чтение. Для таких простых команд, как в листинге 3.1, это не нужно, но разбиение пригодится при работе со сложными командами SQL с многочисленными секциями, выражениями и условиями. В книге периодически встречаются примеры, в которых команда разбивается на несколько строк с комментариями к каждой части.
Операторы в командах SQL
Листинг 3.10. Операторы в командах SQL
booktown=# SELECT * FROM books;
id | title author_id | subject_id
7808 | The Shining |4156 | 9
156 | The Tell-Tale Heart| 15| 9
4513 | Dune |1866 |15
4267 | 2001: A Space Odyssey| 2001| 15
1608 | The Cat in the Hat |1809| 2
1590 | Bartholomew and the Oobleck |1809| 2
(6 rows)
booktown=# UPDATE books SET author_id = author _id + 1500;
UPDATE 6
booktown=# SELECT * FROM books;
id title | author_id | subject_id
7808 | The Shining | 5656 | 9
156 | The Tell-Tale Heart 1515| 9
4513| Dune 3366 | 15
4267 | 2001; A Space Odyssey 3501 | 15
1608 | The Cat in the Hat | 3309 |2
1590 | Bartholomew and the Oobleck | 3309 | 2
Как видно из листинга 3.10, выполнение операции сложения с предыдущим значением поля author_id приводит к модификации этого поля во всех записях таблицы.
Вероятно, вы уже знакомы с основными математическими операторами: + (суммирование двух числовых величин), - (вычитание) и т. д. Существуют и другие, более экзотические операторы — например, поразрядные операторы & и |, которые модифицируют значения на уровне двоичного представления.
Некоторые ключевые слова SQL также часто относятся к категории операторов. В первую очередь это логические операторы AND, OR и NOT. Формально являясь ключевыми словами, они причисляются к операторам, поскольку предназначаются для выполнения операций с константами и идентификаторами.
Основные операторы PostgreSQL перечислены в табл. 3.6.
Однострочные комментарии
Листинг 3.11. Однострочные комментарии
testdb=# SELECT 'Test1 -- This can follow valid SQL tokens.
testdb-# -- or be on a line of its own. testdb-#
AS example; example
Test
(1 row)
Многострочные комментарии начинаются с последовательности /* и завершаются последовательностью */. Такой способ оформления комментариев хорошо знаком программистам С, но между интерпретатором PostgreSQL и компилятором С существует одно принципиальное отличие: комментарии PostgreSQL могут быть вложенными. Иначе говоря, если внутри многострочного комментария имеется другой многострочный комментарий, то закрывающая последовательность */ внутреннего комментария не закрывает внешний комментарий. Пример многострочного комментария приведен в листинге 3.12.
Многострочные комментарии
Листинг 3.12. Многострочные комментарии
testdb=# SELECT 'Multi /* This comment extends across
testdb-# * numerous lines, and can be
testdb-# * /* nested safely */ */
testdb-# | '-test' AS example; example
Multi-test (1 row)
Допустим, имеется файл с кодом SQL, в котором необходимо закомментировать большой фрагмент и передать остаток PostgreSQL для интерпретации и выполнения. Если в этом фрагменте встречаются многострочные комментарии, PostgreSQL правильно заключает, что закрывающая последовательность */ относится к последнему открытому комментарию, а не ко всему закомментированному блоку.
Примечание 1
Примечание 1
Звездочка (без смежного символа косой черты) не имеет особой интерпретации в комментариях. Дополнительные звездочки были включены в листинг 3.12 исключительно по эстетическим сообщениям.
Пример запроса SQL
Листинг 3.13. Пример запроса SQL
booktown=# SELECT Id, name FROM states;
id | name
42 | Washington 51 I Oregon
(2 rows)
booktown=#
В табл. 3.8 и 3.9 анализируется другая, более сложная команда SQL. В ней используется действие UPDATE с секциями SET и WHERE, которые определяют соответственно правило изменения записей и критерий их отбора.
Обновление таблицы командой UPDATE
Листинг 3.14. Обновление таблицы командой UPDATE
booktown=# UPDATE states
booktown-# SET id = 51
booktown-# WHERE
name = 'Oregon';
UPDATE 1
booktown=# SELECT * FROM states
booktown-$ WHERE
name='Oregon':
Id | name | abbreviation
51 | Oregon | OR
(1 row)
booktown=#
Пустые строки и NULL
Листинг 3.15. Пустые строки и NULL
booktown=# SELECT id. title FROM books:
id [ title
7808 | The Shining 156 | The Tell-Tale
Heart 4513 | Dune
100 |
101 | (5 rows)
booktown=# SELECT id. title FROM
books WHERE title = ": id | title
100 (1 row)
Dooktown=# SELECT id, title FROM
books WHERE title IS NULL;
id title
101 |
(1 row)
В листинге 3.16 продемонстрировано более практичное (и реальное) применение ключевого слова NULL в таблице editions, связывающей код ISBN с датой публикации книги.
Пример использования NULL
Листинг 3.16. Пример использования NULL
booktown=# SELECT isbn, publication FROM editions:
isbn | publication
039480001X | 1957-03-01
0394800753 | 1949-03-01
0385121679 | (3 rows)
booktown=# SELECT isbn. publication FROM
editions WHERE publication IS NULL:
isbn | publication
0385121679 |
(1 row)
В этом примере NULL может использоваться для представления изданий, которые еще не были опубликованы или дата публикации которых на момент занесения данных в базу неизвестна. Было бы неправильно подбирать для таких книг какую-нибудь бессмысленную дату, и в обоих случаях NULL выглядит вполне оправданно.
Простая таблица с логическими значениями
Листинг 3.17. Простая таблица с логическими значениями
booktown=# CREATE TABLE daily_inventory
(isbn text. in_stock boolean);
CREATE
booktown=# INSERT INTO
dailyjnventory VALUES ('0385121679', true);
INSERT 3390926 1
booktown=# INSERT INTO dailyjnventory
VALUES ('039480001X'. 't');
INSERT 3390927 1
booktown=# INSERT INTO dailyjnventory
VALUES ('044100590X'. 'true');
INSERT 3390928 1
booktown=# INSERT INTO dailyjnventory
VALUES С0451198492', false);
INSERT 3390929 1
booktown=# INSERT INTO dailyjnventory
VALUES С0394900014', '0');
INSERT 3390930 1
booktown=# INSERT INTO dailyjnventory
VALUES ('0441172717'. '!');
INSERT 3390931 1
booktown=# INSERT INTO dailyjnventory
VALUES ('0451160916');
INSERT 3390932 1
После того как таблица заполнена, можно легко получить информацию об имеющихся в наличии книгах. Для этого используется запрос SELECT, приведенный в листинге 3.18.
Выборка данных по логическому признаку
Листинг 3.18. Выборка данных по логическому признаку
booktown=# SELECT * FROM dailyjnventory WHERE in_stock='yes':
isbn in_stock
0385121679 | t
039480001X | t
044100590X t
0441172717 I t
(4 rows)
В PostgreSQL предусмотрена возможность неявной выборки по значению true в логическом поле; для этого имя поля указывается без операторов или ключевых слов-модификаторов. В хорошо спроектированных таблицах такой подход помогает создавать более наглядные запросы. Пример приведен в листинге 3.19.
Неявная выборка по логическому значению
Листинг 3.19. Неявная выборка по логическому значению
true booktown=# SELECT * FROM dailyjnventory WHERE in_stock;
isbn | in_stock
0385121679 | t
039480001X | t
044100590X | t
0441172717 | t
(4 rows)
Хотя в этом запросе не указана конкретная логическая величина, при отсутствии оператора сравнения подразумевается значение true.
Для выборки по значению false можно либо сравнить значение поля с любой из логических констант, перечисленных в табл. 3.11, либо поставить перед именем поля ключевое слово SQL NOT. Оба способа продемонстрированы в листинге 3.20.
Ключевые слова и команды
Листинг 3.2. Ключевые слова и команды
booktown=# INSERT INTO states VALUES (33, 'Oregon', 'OR');
INSERT 3389701 1
В листинге 3.2 команда SQL INSERT INTO содержит ключевые слова SQL INSERT, INTO и VALUES.
Команда INSERT INTO модифицирует таблицу, заданную идентификатором states. В данном случае модификация сводится к вставке новой записи.
Выборка по логическому значению false
Листинг 3.20. Выборка по логическому значению false
booktown=# SELECT * FROM dailyjnventory WHERE in_stock = 'no';
isbn | in_stock
0451198492 f 0394900014 f (2 rows)
booktown=# SELECT * FROM dailyjnventory
WHERE NOT in_stock:
isbn | in_stock
0451198492 | f
0394900014 | f
(2 rows)
Этот пример убедительно доказывает, что при проектировании языка SQL учитывался фактор наглядности и удобочитаемости программ. При грамотном выборе имен таблиц и полей запрос почти не отличается от обычной фразы на английском языке.
Сравнение значений логических полей с константами из табл. 3.11 может осуществляться при помощи оператора неравенства != (например, WHERE in_stock != 't'). Таким образом, следующие три синтаксические формы эквивалентны:
SELECT * FROM daily_iinventory
WHERE NOT injtock: SELECT * FROM
dailyjnventory WHERE in_stock = 'no1:
SELECT * FROM dailyjnventory WHERE in_stock != 't':
Возможно, вы обратили внимание на то, что в листинге 3.17 в таблицу вставляется семь записей, а суммарное количество записей при двух выборках (для поля i n_stock, равного true и fal se) только шесть. Дело в том, что в последней операции вставки в листинге 3.17 значение поля i n_stock не указано, поэтому в записи книги с кодом ISBN равным 0451160916 поле in_stock равно NULL.
Как упоминалось выше, величина NULL не интерпретируется как true или fal se, поэтому для выборки по значению NULL необходимо использовать условие IS NULL. Также можно воспользоваться оператором ! =, но тогда возникают проблемы с адаптацией программы для других СУБД. Пример запроса SQL с условием IS NULL:
booktown=# SELECT * FROM
dailyjnventory WHERE in_stock IS NULL:
isbn | 1n_stock
0451160916 |
(1 row)
Поскольку IS NULL является обычным условием SQL, для обновления всех случайных значений NULL в поле in_stock можно воспользоваться командой UPDATE, приведенной в листинге 3.21.
Исправление случайных значений NULL
Листинг 3.21. Исправление случайных значений NULL
booktown=# UPDATE dailyjnventory
SET in_stock = Т WHERE in_stock IS NULL;
UPDATE 1
Использование типа numeric вместо money
Листинг 3.23. Использование типа numeric вместо money
booktown=# CREATE TABLE money_example (money_cash money.
booktown(# numeric_cash numeric(10,2)):
CREATE
booktown=# INSERT INTO money_example VALUES C$12.241, 12.24);
INSERT 3391095 1
booktown=# SELECT * FROM money_example;
money_cash | numeric_cash
$12.24 | 12.24 (1 row)
booktown=# SELECT money_cash,
booktown-# '$' | ltrim(to_char(numenc_cash. '9999.99'))
booktown-# AS numeric_cashif1ed
booktown-# FROM money_example;
money_cash | numeric_cashified
$12.24 j 12.24
(1 row)
Использование типа serial
Листинг 3.24. Использование типа serial
booktown=# CREATE TABLE autojdentified (id_serial);
NOTICE: CREATE TABLE will create implicit sequence '
auto Jdentif led Jd_seq'
for SERIAL column 'auto_identified.id'
NOTICE: CREATE TABLE/UNIQUE will create
Implicit index 'auto_identified_1d_key' for table
'autojdentified'
CREATE
Решение задачи «вручную»
Листинг 3.25. Решение задачи «вручную»
booktown=# CREATE SEQUENCE autojdentified id_seq;
CREATE
booktown=# CREATE TABLE autojdentified
booktown-# (id integer UNIQUE DEFAULT
nextval('autojdentifiedjd_seq'));
NOTICE: CREATE TABLE/UNIQUE will create implicit index
'autojdentifiedjdjcey' for table
'autojdentified'
CREATE
ВНИМАНИЕ
После удаления таблицы последовательность, созданная для типов senal, автоматически не удаляется. При удалении таблиц, содержащих поля типа serial, эти последовательности должны удаляться отдельно.
Выбор формата даты
Листинг 3.26. Выбор формата даты
booktown=# SET DATESTYLE TO ISO,US;
SET VARIABLE
booktown=# SHOW DATESTYLE;
NOTICE: DateStyle is ISO with
US (NonEuropean) conventions
SHOW VARIABLE
booktown=f SET DATESTYLE TO
NONEUROPEAN. GERMAN;
SET VARIABLE
booktown=# SHOW DATESTYLE;
NOTICE: DateStyle is German
with European conventions
SHOW VARIABLE
Если дополнительный формат не указан, по умолчанию выбирается подходящее значение (например, для регионального формата German выбирается значение European).
Хотя переменная DATESTYLE является удобным средством настройки формата даты, необходимо помнить, что она относится к категории переменных времени исполнения, а это означает, что настройка действует лишь на протяжении текущего сеанса. Существует два способа присвоить переменной DATESTYLE значение по умолчанию, чтобы его не приходилось указывать заново при каждом сеансе.
- Изменение переменной среды PGDATESTYLE на сервере, на котором работает процесс postmaster. Например, при использовании командного интерпретатора bash можно добавить строку PGDATESTYLE="SQL US" в файл .bash_profile пользователя postgres. При запуске процесса postmaster пользователем postgres переменная PGDATESTYLE будет автоматически применяться ко всем операциям форматирования даты и времени, выполняемым PostgreSQL.
- Изменение переменной среды PGDATESTYLE, используемой клиентским приложением (при условии, что оно было написано с применением библиотеки libpq) в начале сеанса. Этот вариант выбирается в том случае, если формат вывода должен настраиваться клиентом, а не сервером. Например, присваивая значение переменной PGDATESTYLE командой export в приглашении bash перед запуском клиента psql, вы задаете формат, который будет использоваться в работе psql.
Операции с интервалами
Листинг 3.27. Операции с интервалами booktown=# SELECT date('1980-06-25');
date
1980-06-25
(1 row)
booktown=# SELECT interval С 21 years 8 days');
interval
21 years 8 days (1 row)
booktown=# SELECT date('1980-06-25') + interval
('21 years 8 days') booktown-# AS spanned_date:
spanned_date
2001-07-03 00:00:00-07
(1 row)
booktown=# SELECT date ('1980-06-25') -
interval ('21 years 8 days ago1)
booktown-# AS twice_inverted_interval_date;
twice_ nverted_interval_date
2001-07-03 00:00:00-07
(1 row)
Использование констант current и now
Листинг 3.28. Использование констант current и now
booktown=# CREATE TABLE tasklog
booktown=# (taskname char(15),
booktown=# timebegun timestamp,
booktown=# timeflnished timestamp);
CREATE
booktown=# INSERT INTO tasklog VALUES
booktown=# ('delivery', 'now', 'current'):
INSERT 169936 1
booktown=# INSERT INTO tasklog
VALUES booktown=# ('remodeling', 'now', 'current');
INSERT 169937 1
booktown=# SELECT taskname, tlmefnished - timebegun
booktown-# AS timespent FROM tasklog;
taskname | timespent
delivery | 00:15-.32
remodeling [ 00:04:42
(2 rows)
Итак, константа now обычно используется при сохранении в таблице фиксированного момента времени, который не изменяется при последующих ссылках. Как видно из листинга 3.29, плохое понимание различий между константами now и current приводит к потенциальным ошибкам программирования SQL. В листинге приведены две команды INSERT; в первой команде используется now, а во второй — current. Сравнение результатов показывает, что в первой строке при каждом запросе время обновляется, а во второй строке оно всегда остается одинаковым.
Сравнение констант now и current
Листинг 3.29. Сравнение констант now и current
booktown=# INSERT INTO shipments (customer_id. isbn, ship_date)
Ccustomer_id, isbn, ship_date)
booktown-# VALUES (1. '039480001X', 'current');
INSERT 3391221 1
booktown=# INSERT INTO shipments (customer_id. isbn, ship_date)
booktown-# VALUES (2. '0394800753'. 'now');
INSERT 3391222 1
booktown=# SELECT isbn. ship_date FROM shipments: isbn | ship_date
039480001X [ current 0394800753 | 2001-08-10 18:17:49-07
(2 rows)
booktown=# SELECT isbn.
booktown-# to_char(ship_date. 'YYYY-MM-DD HH24:MI:SS')
booktown-# AS value
booktown-# FROM shipments; isbn value
039480001X | 2001-08-10 18:21:22 0394800753 | 2001-08-10 18:17:49
(2 rows)
booktown=# SELECT isbn.
booktown-# to_char(ship_date. 'YYYY-MM-DD HH24:MI:SS')
booktown-# AS value
booktown-# FROM shipments;
isbn | value
039480001X | 2001-08-10 18:22:35 0394800753 | 2001-08-10 18:17:49
(2 rows)
Преодоление ограничений
Листинг 3.3. Преодоление ограничений
booktown=# CREATE TABLE lst_bent_rule (rule_name text);
ERROR: parser: parse error at or near "1"
booktown=# CREATE TABLE "lst_bent_rule" (rule_name text);
CREATE
Более того, имена таблиц могут содержать некоторые символы, которые обычно считаются недопустимыми (например, пробелы или амперсанды, хотя присутствие кавычек, разумеется, запрещено). Хотя стандарт ANSI/ISO SQL не позволяет создавать идентификаторы с именами, совпадающими с ключевыми словами SQL, PostgreSQL (как и ряд других реализаций SQL) достаточно либерально относится к этому ограничению.— такие имена допустимы, но они должны заключаться в кавычки.
Защита идентификаторов при помощи кавычек выручает во многих нестандартных ситуациях, но если вы хотите, чтобы ваши команды SQL были стандартными и хорошо адаптировались для других платформ, старайтесь по возможности придерживаться стандартов ANSI/ISO.
Использование функции преобразования типа
Листинг 3.30. Использование функции преобразования типа
booktown=# SELECT text(1000)
booktown-# AS explicitjtext;
explicit_text
Идентификация записей по OID
Листинг 3.31. Идентификация записей по OID
3Stdb=# SELECT * FROM my_list;
todos
----------------------------------
Correct redundancies In my_list.
Correct redundancies in my_list.
(1 rows)
testdb=# SELECT *. old FROM my_list:
todos | old
----------------------------------------
Correct redundancies in my list. | 3391263
Correct redundancies In my list. | 3391264
( 2 rows)
testdb=# DELETE FROM my_list
testdb-# WHERE old = 3391264;
DELETE 1
testdb=# SELECT *.oid FROM my_list;
todos old
----------------------------------------------
Correct redundancies in my list. | 3391263
(1 row)
Использование строковых констант
Листинг 3.4. Использование строковых констант
booktown=# UPDATE authors
booktown-# SET firstjiame = 'Louisa May'
booktown-l WHERE firstjiame = 'Luoisa May'
UPDATE 1
booktown-# SELECT * FROM authors;
id | lastjiame | firstjiame
1809 | Geisel | Theodor Seuss
1111 | Denham | Ariel 15990 | Bourgeois | Paulette
25041 | Bianco j Margery Williams
115 I Poe I Edgar Allen
16 j Alcott I Louisa May
(6 rows)
Команда UPDATE в листинге 3.4 использует строковые константы Louisa May и Luoisa May в сочетании с ключевыми словами SET и WHERE. Как видно из результатов запроса, команда обновляет содержимое таблицы, заданной идентификатором authors, и исправляет опечатку.
Тот факт, что строковые константы заключаются между апострофами, порождает очевидную семантическую проблему: если в самой последовательности символов встречается апостроф, граница строковой константы будет определена неверно. Чтобы экранировать апостроф в строке (то есть обеспечить его интерпретацию как литерала), следует поставить два апострофа подряд. Модуль лексического анализа воспринимает удвоенный апостроф в строковой константе как один апостроф-литерал. PostgreSQL также позволяет экранировать апострофы обратной косой чертой, в стиле языка С:
testdb=# SELECT 'PostgreSQL"s great!' AS example;
example
PostgreSQL's great! (1 row)
booktown=# SELECT 'PostgreSQLN's
С-style slashes are great!' AS example;
example
PostgreSQL's C-style slashes are great!
(1 row)
В PostgreSQL также поддерживаются служебные последовательности языка С, перечисленные в табл. 3.3.
Разбиение строковых констант
Листинг 3.5. Разбиение строковых констант
booktown=# SELECT 'book'
booktown-#
booktown-# 'end' AS example;
example
bookend (1 row)
booktown=# SELECT 'bookend' AS example;
example
bookend
(1 row)
Обе команды имеют эквивалентную семантику. Тем не менее фрагменты должны разделяться хотя бы одним разрывом строки, а при попытке разделить их только пробелами PostgreSQL выдает сообщение об ошибке:
booktown=# SELECT 'book' 'end' AS example;
ERROR: parser: parse error at or near .....
Дело в том, что без разрыва строки PostgreSQL считает, что вы ссылаетесь на две отдельные константы. Объединение двух строковых констант в одной строке выполняется оператором конкатенации 11, описанным в главе 5:
booktown=# SELECT 'book.' || 'end1 AS example; example
bookend (1 row)
Использование битовых последовательностей
Листинг 3.6. Использование битовых последовательностей
testdiH* INSERT INTO my_bytes VALUES (B'OOOOOOOO'):
testdb=# SELECT my_byte FROM my_bytes:
my_byte
10000000
10000001
10000101
11111111
00000000
(5 rows)
Использование целочисленных констант
Листинг 3.7. Использование целочисленных констант
booktown=# SELECT * FROM
authors WHERE id < 100;
id | lastjiame | firstjiame
16 | Alcott | Louisa May (1 row)
booktown=# SELECT * FROM authors WHERE id = 100:
id | lastjiame | firstjiame
(0 rows)
booktown=# UPDATE authors
booktown-* SET id = 116
booktown-tf WHERE id = 16:
UPDATE 1
booktown=# SELECT * FROM authors WHERE id = 116:
id | last_name firstjiame
116 | Alcott | Louisa May (1 row)
В листинге 3.7 секция WHERE команды SELECT сравнивает идентификатор поля id с целочисленной константой 100. Результат состоит из одной записи. После обнаружения записи с недопустимым значением id вводится вторая команда SELECT, которая проверяет, существуют ли в таблице записи с кодом i d=116. Мы убеждаемся в том, что код 116 не задействован в таблице authors, поскольку значения в поле id должны быть уникальными. Операция завершается командой UPDATE, также содержащей целочисленные константы в секциях SET и WHERE.
Допустимые вещественные значения
Листинг 3.8. Допустимые вещественные значения
booktown=# SELECT .04 AS small_float.
booktown-# -16.63 AS negative_float,
booktown-# 4e3 AS exponent!al_float,
booktown-# 6.1e2 AS negative_exponent:
small_float | negative_float |
exponential__float | negative_exponent
0.04 -16.63 4000 | 0.061
(1 row)
Различия между true и 'true'
Листинг 3.9. Различия между true и 'true'
testdb=# SELECT true AS boolean_t. testdb-# 'true' AS string_t,
testdb-# false AS boolean_f,
testdb-# 'false' AS string_f;
boo1_t | string_t | bool_f | string_f
t | true | f | false
(1 row)
Как показано в листинге 3.9, PostgreSQL выводит значения логического типа в виде t или f, однако это вовсе не означает, что символы t и f могут использоваться в качестве логических констант. PostgreSQL не сможет правильно интерпретировать их, что приведет к ошибке.
Логические константы
Логические константы
Логические (булевы) константы гораздо проще всех остальных типов констант PostgreSQL, поскольку они принимают всего два допустимых значения: true и false. Встретив любое из этих значений, не заключенное в апострофы, PostgreSQL интерпретирует его как логическую константу. Пример показан в листинге 3.9.
Логические значения
Логические значения
Логическим значением называется простая структура данных, представляющая одну из двух величин: true или f al se. В PostgreSQL поддерживается тип данных boo! ean, определенный в стандарте SQL99, с нестандартным синонимом bool.
Логическим переменным, как и другим типам данных, может присваиваться значение NULL, Логическая переменная, равная NULL, никогда не интерпретируется как true или false; она интерпретируется только как NULL. Если вы хотите проверить, равна ли логическая переменная псевдозначению NULL, не пытайтесь сравнивать ее с false, это бессмысленно. Для этой цели следует использовать конструкцию IS NULL. Способность логической переменной принимать значения true, false и NULL (и правила, в соответствии с которыми NULL считается отличным от этих двух величин) называется тройственной логикой.
В табл. 3.11 приведены допустимые обозначения логических констант, правильно опознаваемые PostgreSQL. Выбор обозначений является делом вкуса. Все разновидности значения true, как и все разновидности значения fal se, интерпретируются сервером одинаково.
Массивы константы
Массивы - константы
При вставке в поле таблицы нового значения, которое представляет собой массив, в команде SQL необходимо перечислить входящие в него элементы. В соответствии с синтаксисом массивов-констант перечисляемые элементы ограничиваются символами-разделителями (запятыми для встроенных типов) и заключаются в фигурные скобки, которые, в свою очередь, заключаются в апострофы: '{ элемент!, элемент2 [ . ...] }'
В этом синтаксисе элементы могут относиться к любому из допустимых типов PostgreSQL. Поскольку весь массив заключается в апострофы, все апострофы внутри элементов массива должны экранироваться как в обычных строковых константах. С другой стороны, выбор запятой в качестве символа-разделителя создает интересную проблему при работе с символьными строками, содержащими запятые, поскольку не заключенные в апострофы запятые интерпретируются как разделители. Но как упоминалось выше, в массивах-константах в апострофы должен заключаться лишь весь массив, а не его отдельные элементы.
В PostgreSQL эта проблема решается заключением строковых констант в кавычки в тех случаях, когда вне контекста массива обычно используются апострофы: '{"valuel","value 2. which contains a comma" }'
Помните, что для правильной интерпретации PostgreSQL массивы обязательно должны заключаться в апострофы. Массив-константу можно рассматривать как особую разновидность строковых констант, которая интерпретируется как массив в зависимости от контекста (например, при добавлении новых данных в поле, имеющее тип массива). В другой ситуации PostgreSQL интерпретирует эту константу как обычный строковый литерал (последовательность символов, заключенная в апострофы), который просто содержит фигурные скобки.
Массивы в таблицах
Массивы в таблицах
В PostgreSQL предусмотрен синтаксис для определения массивов как фиксированного, так и переменного размера; тем не менее в PostgreSQL 7.1.2 ограничение размера не соблюдается. Это означает, что с точки зрения программы массив может иметь фиксированный размер, но при этом изменение размеров все равно производится динамически. Например, поле таблицы, определенное как массив из трех элементов, может содержать три элемента в одной записи, четыре элемента в другой и вообще не содержать элементов в третьей.
Также допускается определение многомерных массивов, в которых каждый элемент может быть не атомарным значением, а другим массивом. При выборке из многомерных массивов элементы выводятся во вложенных фигурных скобках:
booktown=# SELECT editions FROM myjiotes
WHERE title='The Cat In the Hat';
editions
{{"039480001X"."lst Ed. hard Cover"}.
{"039400014"."1st Ed"}} Cl row)
Массивы
Массивы
В исходном варианте реляционной модели значения полей таблиц должны представлять собой атомарные объекты данных. В объектно-реляционных базах данных, к которым относится PostgreSQL, в структурах данных могут использоваться составные значения, называемые массивами.
Массив представляет собой совокупность элементов с общим идентификатором. Элементы массива могут относиться как к встроенному, так и к пользовательскому типу данных, но они обязательно должны быть однотипными. При обращении к элементам массива используется индексная запись с квадратными скобками (например, ту_аггау[0]). Элементы массивов-констант перечисляются в фигурных скобках, заключенных в апострофы (например, '{value_one.value_two,value_three}').
Обязательная защита идентификаторов
Обязательная защита идентификаторов
Идентификаторы обязательно должны заключаться в кавычки только в двух случаях: если идентификатор объекта базы данных совпадает с ключевым словом или в его имени присутствует хотя бы одна прописная буква. В любом из этих случаев идентификатор должен защищаться как при создании объекта, так и при последующих ссылках на него в командах SELECT, DELETE или UPDATE и т. д.
Если не заключить в кавычки идентификатор, совпадающий с ключевым словом, PostgreSQL выдаст сообщение об ошибке, поскольку идентификатор интерпретируется как ключевое слово. Допустим, имеется таблица с именем select. При попытке обратиться к ней со следующим запросом вы получите сообщение об ошибке:
testdb=# SELECT * FROM select
ERROR: parser: parse error at or near "select"
Как показывает этот пример, запрос к незащищенному идентификатору таблицы select приводит к ошибке. Чтобы идентификатор select воспринимался как имя таблицы, а не как ключевое слово, его необходимо заключить в кавычки. Таким образом, правильный запрос к таблице с именем sel ect должен выглядеть так:
testdb=# SELECT * FROM "select";
selected
1
52 105 (4 rows)
Аналогично следует поступать и с идентификаторами, содержащими хотя бы один символ верхнего регистра. Например, если вы по какой-либо причине создали таблицу с именем ProDucts (обратите внимание на прописные буквы Р и D) и теперь хотите ее уничтожить (еще бы, с таким именем!), идентификатор также следует заключить в кавычки:
D0oktown=# DROP TABLE ProDucts;
iRROR: table "products" does not exist
booktown=# DROP TABLE "ProDucts";
DROP
Защита идентификаторов иногда бывает чрезвычайно полезной, даже если вы зсегда создаете объекты базы данных только с «правильными» именами. Наприпер, при импортировании данных через внешнее соединение ODBC (например, is Microsoft Access) имена созданных таблиц могут быть записаны символами верх-iero регистра. Без защиты идентификаторов вам не удастся использовать такие габлицы в программе.
Операторы
Операторы
Другую категорию специальных символов составляют операторы, предназначенные для выполнения различных операций с идентификаторами или константами. Операторы могут использоваться как для математических вычислений (сложение, вычитание и т. д.), так и для сравнения и логических операций.
Вернемся к таблице books и ее числовому полю author_id. Вспомните, что в этом поле хранится целочисленный код, определяющий автора книги. Теперь представьте, что вследствие модификации системы все коды авторов должны быть увеличены на 1500. Задача решается командой UPDATE и выполнением операции с полем author_id. При этом используется оператор сложения (+). Пример приведен в листинге 3.10.
Предварительное планирование
Предварительное планирование
Прежде чем переходить к непосредственному созданию таблиц, желательно выде-ить немного времени на предварительное планирование объектов базы данных, также на выбор имени, типа и смысла каждого поля в таблице. В результате пла-ирования схема выбора имен становится более стройной и последовательной, это, в свою очередь, приводит к появлению более наглядных и «вразумительных» команд и запросов.
Кроме перечисленных семантических факторов (имена, типы и смысл полей), еобходимо проследить за четким установлением связей между таблицами. Проек-ирование связей является важной частью процесса проектирования таблиц, по-кольку любые ошибки в этой области — как дублирование больших объемов дан-ых, так и случайное исключение важных данных из таблиц — являются крайне ежелательными.
Вернемся к таблице books базы данных booktown, структура которой приведена табл. 3.1. В полях каждой записи хранится внутренний код книги, название, код втора и код темы. Обратите внимание: вместо полного имени автора и текстового писания темы в таблице хранятся простые целочисленные коды, используемые ля связи с двумя другими таблицами: authors и subjects. Содержимое этих таблиц астично иллюстрируют табл. 3.26 и 3.27.
Преобразование типов
Преобразование типов
В PostgreSQL поддерживаются три отдельных варианта синтаксиса преобразования (приведения) типов, то есть механизма приведения данных от одного типа к другому. В команде SQL преобразование типов позволяет явно задать тип создаваемой константы (вместо его косвенного определения по правилам языка).
В общем случае приведение строковой константы к другому типу может выполняться любым из трех способов:
тип 'значение'
'значение': -.тип
CAST ('значение' AS тип)
Числовые константы преобразуются в символьную строку следующими способами:
значение: : тип
CAST (значение AS тип)
Здесь значение представляет константу, тип которой требуется изменить, а тип — новый тип этой константы.
Примечание 1
Примечание 1
Помните, что тип money считается устаревшим, что несколко затрудняет его использование в преобразованиях.
Преобразование к другому типу данных не ограничивается одними константами. Поля набора данных, возвращаемого запросом SQL, также могут преобразовываться к другому типу, при этом используются следующие формы синтаксиса:
идентификатор:: тип
CAST (идентификатор AS тип)
Следует учесть, что не каждый тип данных может быть приведен к любому другому типу. Например, не существует осмысленного преобразования символьной строки abed в двоичную последовательность типа bit. Недопустимые попытки преобразования приводят к ошибкам PostgreSQL. Чаще всего встречаются преобразования символьных строк, типов даты/времени или числовых типов к типу text, а также символьных строк в числа.
Кроме синтаксических форм преобразования типа существуют некоторые функции, позволяющие добиться практически того же результата. Имена этих функций часто совпадают с именами итоговых типов (например, text()), хотя существуют и узкоспециализированные варианты (например, bitfromint4()). В листинге 3.30 приведен пример использования функции text О для преобразования целого числа 1000 в строку типа text, содержащую символы «1000».
Псевдозначение NULL
Псевдозначение NULL
Выше говорилось о том, что с каждым полем ассоциируется определенный тип данных и поле принимает значения только этого типа. Тем не менее существует значение, которое может храниться в любых полях независимо от типа; в SQL оно представлено ключевым словом NULL. Ключевое слово NULL не соответствует конкретному объекту данных и потому вообще не считается типом; это системное ключевое слово, которое указывает базе данных на то, что поле не содержит никакого значения. Единственное исключение из правила об универсальности NULL составляют поля, для которых установлено ограничение NOT NULL.
Ключевое слово NULL часто используется для представления необязательных значений. Оно позволяет обойтись без странных и противоестественных схем, например представления отсутствующих данных в целочисленном поле отрицательными числами. Ситуация со временем может измениться, но NULL — всегда NULL.
NULL можно рассматривать как псевдозначение, то есть признак отсутствия значения, который никогда не может быть эквивалентен значению, отличному от NULL. Одна из распространенных ошибок при работе с псевдозначениями NULL связана с тем, что их часто путают с пустыми символьными строками. Отчасти это связано с тем, что при выборке пустой строки данные в клиенте не выводятся. При выборке NULL происходит то же самое, однако NULL принципиально отличается от пустых строк, и это необходимо хорошо понимать, чтобы ваши запросы правильно работали. Поле строкового типа, содержащее пустую строку, содержит последовательность символов, хотя бы и пустую; таким образом, поле имеет определенное значение. Ключевое слово NULL обозначает полное отсутствие значения в поле.
Это весьма принципиальное различие, поскольку правила выполнения операций SQL с пустыми строками очень отличаются от правил операций с псевдозначениями NULL. Особенно заметно эти различия проявляются при объединениях, рассматриваемых в главе 4.
Примеры выборки NULL и пустых строк приведены в листинге 3.15. Первый запрос SELECT показывает, что записи двух книг были вставлены в таблицу без названий (поле ti tie). Тем не менее из последующих запросов становится видно, что в одной записи (id=100) это поле содержит пустую строку, а в другой записи — NULL
Символьные типы
Символьные типы
Символьные типы используются в любых операциях с символьными данными (например, с фрагментами текста в кодировке ASCII). Обычно они применяются для хранения имен, адресов и т. д.
В стандартном языке SQL поддерживаются два символьных типа character и character varyi ng. В PostgrcSQL к ним добавился обобщенный тип text, не требующий явного задания максимального размера поля. Размер полей типа text автоматически изменяется в соответствии с объемом хранящихся данных и практически не ограничивается (размер поля не может превышать один гигабайт, но на практике поля такого размера почти не встречаются). В табл. 3.12 перечислены символьные типы данных PostgreSQL.
Синтаксические символы
Синтаксические символы
Некоторые специальные символы выполняют в командах SQL примерно те же функции, что и знаки препинания в английском языке. В табл. 3.5 перечислены основные синтаксические символы PostgreSQL.
Системные поля
Системные поля
В PostgreSQL все таблицы содержат системные поля, которые остаются невидимыми для пользователя и не выводятся при выборке (если служебная информация не запрашивается специально). В системных полях хранятся метаданные, описывающие содержимое записей. Некоторые из них позволяют различать кортежи (фиксированные состояния записей) при работе с блоками транзакций (за дополнительной информацией о транзакциях обращайтесь к главе 7).
В табл. 3.25 перечислены системные поля, присутствующие в каждой записи в дополнение к полям, определенным пользователем в структуре таблицы.
Совместимость
Совместимость
Для сохранения совместимости с предыдущими версиями PostgreSQL разработчики продолжают поддерживать типы данных datetime и timespan. Тип datetime эквивалентен timestamp, а тип timespan — типу interval.
К числу типов даты/времени также относятся типы abstime и reltime, обладающие пониженной точностью представления. Тем не менее это внутренние типы PostgreSQL, которые могут исчезнуть в следующих версиях. Старайтесь использовать только SQL-совместимые типы данных и как можно скорее устранить устаревшие типы из существующих приложений.
Специальные символы
Специальные символы
Специальные символы имеют особое синтаксическое значение в PostgreSQL. По этой причине они обычно не могут использоваться в идентификаторах, хотя, как упоминалось выше в пункте «Защищенные идентификаторы» подраздела «Ключевые слова и идентификаторы», данное ограничение обычно удается обойти при помощи кавычек.
Стандарты SQL
Стандарты SQL
В 1986 году язык SQL был стандартизирован Американским национальным институтом стандартов (ANSI), а в 1987 году появился стандарт Международной организации по стандартам (ISO). Стандарт ANSI/ISO был принят в качестве Федерального стандарта по обработке информации (FIPS) правительства США. В 1989 году был опубликован пересмотренный стандарт, который обычно обозначается сокращениями «SQL89» и «SQL1».
По некоторым причинам (отчасти из-за столкновения интересов фирм-разработчиков) стандарт SQL89 был намеренно оставлен незавершенным, а многие возможности были отнесены к разряду «определяемых при реализации». С целью укрепления стандарта комитет ANSI пересмотрел свою предыдущую работу, и в 1992 году был принят стандарт SQL92 (также называемый SQL2). В новом стандарте были исправлены некоторые недостатки SQL89 и намечены концептуальные особенности SQL, которые на тот момент превосходили возможности любых существующих реализаций РСУБД. Кстати, стандарт SQL92 был в шесть раз длиннее своего предшественника. Вследствие расхождений стандарта с текущей ситуацией авторы определили три уровня соответствия SQL92: начальное соответствие (минимальные улучшения в SQL89), промежуточное соответствие (реально достижимый набор принципиальных улучшений) и полное соответствие (стопроцентное выполнение всех положений SQL92).
Позднее, в 1999 году, в ANSI/ISO был опубликован стандарт SQL99, также называемый SQL3. В этом стандарте рассматривались некоторые нетривиальные аспекты современных SQL-систем, в том числе концепции объектно-реляционных баз данных, интерфейсы уровня вызова и обеспечение логической целостности. На смену уровням соответствия SQL92 пришли новые уровни: базовый и расширенный.
В настоящее время PostgreSQL соответствует большинству положений начального уровня стандарта SQL92, а также многим положениям промежуточного и полного уровней. У многих новых положений, появившихся в SQL99, существуют аналоги в области объектно-реляционных концепций PostgreSQL (массивы, функции и наследование).
Строковые константы
Строковые константы
Строковая константа представляет собой произвольную последовательность символов, заключенную в апострофы. Строковые константы часто используются при вставке новых данных в таблицу и при передаче символьной информации другим
объектам базы данных. Ниже приведен пример использования строковых констант при обновлении имен и фамилий таблицы authors базы данных booktown:
booktown=# SELECT * FROM authors;
id | lastjiame | firstjiame
1809 Geisel | Theodor Seuss
1111 | Denham | Ariel
15990 | Bourgeois | Paulette
25041 | Bianco | Margery Williams
16 | Alcott I Luoisa May
115 | Рое | Edgar Allen
(6 rows)
Из результатов запроса видно, что поле firstjiame с кодом id=16, Louisa May, было ошибочно записано в виде Luoi sa May. Ошибка исправляется командой UPDATE со строковой константой, приведенной в листинге 3.4.
Структура имен идентификаторов
Структура имен идентификаторов
Максимальная длина ключевых слов и идентификаторов PostgreSQL равна 31 симюлу. В процессе лексического разбора все ключевые слова и идентификаторы большей длины автоматически усекаются. Идентификаторы начинаются с любой буквы английского алфавита (a-z) или с символа подчеркивания, далее следует фоизвольное сочетание букв, цифр (0-9) и символов подчеркивания. Ключевые лова не могут начинаться или завершаться символом подчеркивания, но для имен щентификаторов это разрешено. Ни ключевые слова, ни идентификаторы не могут начинаться с цифры.
Выше в пункте «Обязательная защита идентификаторов» было показано, что включение идентификатора в кавычки позволяет «преодолеть» правило игнорирования регистра символов. То же относится и к правилу, согласно которому иденификатор не может начинаться с цифры. Хотя без кавычек PostgreSQL не позволит создать таблицу с именем lst_bent_rul e, в кавычках это имя становится приемлемым.
В листинге 3.3 первая команда пытается создать таблицу с недопустимым именем, после чего вторая команда преодолевает это ограничение при помощи кавычек.
Пример таблицы SQL
Таблица 3.1. Пример таблицы SQL
| id | title | authorjd | subjected |
| 7808 | The Shining | 4156 | 9 |
| 156 | The Tell-Tale Heart | 15 | 9 |
| 4513 | Dune | 1866 | 15 |
| 4267 | 2001: A Space Odyssey | 2001 | 15 |
| 1608 | The Cat in the Hat | 1809 | 2 |
| 1590 | Bartholomew and the Oobleck | 1809 | 2 |
Каждая таблица содержит минимум один столбец, однако таблица может не содержать ни одной записи. Каждый вертикальный столбец соответствует фиксированному атрибуту данных, представленных в таблице (как, например, столбец title в таблице books из приведенного выше примера). Без столбцов содержимое соответствующего элемента данных становится неопределенным, тогда как без записей в таблице просто отсутствуют данные. В PostgreSQL 7.1 таблица может содержать до 1600 столбцов и неограниченное количество записей (точнее, ограниченное только аппаратными факторами — например, объемом свободного дискового пространства).
В табл. 3.1 имена столбцов наглядно характеризуют смысл хранящихся в них данных. Впрочем, они выбираются более или менее произвольно, поэтому в процессе планирования имен в таблицах следует помнить о предотвращении возможных конфликтов имен.
Хотя на первый взгляд это и не очевидно, каждый столбец таблицы характеризуется определенным типом данных. Тип данных не только помогает лучше описать информацию, хранящуюся в столбце, но и ограничивает его содержимое. Например, столбец author_id имеет тип Integer; это означает, что любая попытка вставки записи, у которой в этом столбце не находится целое число (например, ПОа), завершится неудачей. Типы данных столбцов подробно описаны в разделе «Типы данных».
В этом разделе были представлены общие принципы логической организации данных в реляционных базах и таблицах. В следующем разделе объясняется, почему все операции с базой осуществляются при помощи команд SQL.
Типы данных PostgreSQL
Таблица 3.10. Типы данных PostgreSQL
| Тип данных | Описание | Стандарт |
| Логические и двоичные типы данных | ||
| boolean, bool | Отдельная логическая величина (true или false) | SQL99 |
| bit(n) | Битовая последовательность фиксированной длины (ровно nбит) | SQL92 |
| bit varying(/7),varbit(rt) | Битовая последовательность переменной длины (до n бит) | SQL92 |
| Символьные типы | ||
| character(n), char(n) | Символьная строка фиксированной длины (ровно n символов) | SQL89 |
| character varying(n), varchar(n) | Символьная строка переменной длины (до n символов) | SQL92 |
| text | Символьная строка переменной или неограниченной длины | PostgreSQL |
| Числовые типы | ||
| small int, int2 | 2-байтовое целое со знаком | SQL89 |
| integer, int, int4 | 4-байтовое целое со знаком | SQL92 |
| bigint, int8 | 8-байтовое целое со знаком, до 18 цифр | PostgreSQL |
| real, float4 | 4-байтовое вещественное число | SQL89 |
| double precision, floats, float | 8-байтовое вещественное число | SQL89 |
| numeric(p.s), decimal (p.s) |
Число из р цифр, содержащее 5 цифр в дробной части | SQL99 |
| money | Фиксированная точность, представление денежных величин | PostgreSQL, считается устаревшим |
| serial | 4-байтовое целое с автоматическим приращением | PostgreSQL |
| Время и дата | ||
| date | Календарная дата (день, месяц и год) | SQL92 |
| time | Время суток | SQL92 |
| time with time zone | Время суток с информацией о часовом поясе | SQL92 |
| timestamp | Дата и время | SQL92 |
| interval | Произвольный интервал времени | SQL92 |
| Геометрические типы | ||
| box | Прямоугольник на плоскости | PostgreSQL |
| line | Бесконечная линия на плоскости | PostgreSQL |
| Iseg | Отрезок на плоскости | PostgreSQL |
| circle | Круг с заданным центром и радиусом | PostgreSQL |
| path | Замкнутая или разомкнутая геометрическая фигура на плоскости | PostgreSQL |
| point | Точка на плоскости | PostgreSQL |
| polygon | Замкнутый многоугольник на плоскости | PostgreSQL |
| Сетевые типы | ||
| cidr | Спецификация сети IP | PostgreSQL |
| inet | Сетевой IP-адрес с необязательными битами подсети | PostgreSQL |
| macaddr | МАС-адрес (например, аппаратный адрес адаптера Ethernet) | PostgreSQL |
| Системные типы | ||
| old | Идентификатор объекта (записи) | PostgreSQL |
| xid | Идентификатор транзакции | PostgreSQL |
Логические константы
Таблица 3.11. Логические константы
| True | False |
| true | false |
| 't' | Т |
| 'true' | 'false' |
| 'У' | 'n' |
| 'yes' | 'no' |
| '1' '0' |
Помните, что все константы, перечисленные в табл. 3.11 (за исключением true и false), должны заключаться в апострофы. В противном случае сервер выдает сообщение об ошибке.
В листинге 3.17 приведен пример создания таблицы da I ly_i inventory с информацией о наличии книг в магазине. В этой таблице код ISBN ассоциируется с логическим признаком. После создания таблица заполняется серией команд INSERT, в которых передается строковая константа (код ISBN) и логические константы в разных форматах.
Символьные типы
Таблица 3.12. Символьные типы
| Тип | Размер | Описание |
| character(rt), chart/7) | (4+ л) байт | Символьная строка фиксированной длины, дополненная пробелами до п символов |
| character varying(/?), varchar(/?) | До (4+л) байт | Символьная строка переменной длины, максимальный размер равен п |
| text | Переменный | Строка переменной длины, максимальный размер не ограничен |
Примечание 1
Примечание 1
Тип данных text не предусмотрен в стандарте ANSI/ISO SQL, однако он поддерживается многими реляционными СУБД, в том числе Sybase и MS SQL Server.
Числовые типы PostgreSQL
Таблица 3.13. Числовые типы PostgreSQL
| Тип | Размер | Допустимые значения |
| bigint, int8 | 8 байт | Целые числа в интервале от -9 223 372 036 854 775 807 до 9 223 372 036 854 775 807 |
| double precision, floats, float | 8 байт | Вещественные числа, 15 значащих цифр, неограниченный размер (с ограниченной точностью) |
| integer, int, int4 numeric(p.s), decimal (p. s) |
4 байта Переменный | Целые числа в интервале от -2 147 483 648 до 2 147 483 647 Целые и вещественные числа из рцифр (всего) и 5 цифр в дробной части |
| real, float4 | 4 байта | Вещественные числа, шесть значащих цифр, неограниченный размер (с ограниченной точностью) |
| small int, int2 | 2 байта | Целые числа в интервале от -32 768 до 32 767 |
| money | 4 байта | Вещественные числа с двумя цифрами в дробной части в интервале от -21 474 836.48 до 21 474 836.47 |
| serial | 4 байта | Целые числа в интервале от 0 до 2 147 483 647 |
Тип numeric Тип numeric (также называемый типом decimal) предназначен для представления сколь угодно больших или малых значений с фиксированной точностью, задаваемой пользователем. При создании таблицы с полем типа numeric в круглых скобках указываются два значения: точность и масштаб. Точность определяет максимальное количество цифр (включая цифры в дробной части), а масштаб определяет количество цифр только в дробной части. Если параметры не заданы, по умолчанию точность равна 30, а масштаб — 6. Максимальная точность (а следовательно, и максимальный размер), задаваемая таким образом, равна 1000. На практике 1000 цифр обычно вполне достаточно.
Примечание 1
Примечание 1
Предотвращение ошибок переполнения
booktcwn=# INSERT INTO numbers
VALUES (9.99999999);
INSERT 3390697 1
booktown=# SELECT * FROM numbers:
number
10.000000 (1 row)
booktown=# INSERT INTO
numbers VALUES (9999.99999999);
ERROR: overflow on numeric
AMS(value) >= 10*5 for field with precision
11 scale 6 booktown=# INSERT INTO
numbers VALUES (trunc(99999.99999999.6));
INSERT 3390698 1
booktown=# SELECT * FROM
numbers; number
10.000000 99999.999999 (2 rows)
booktown=# INSERT INTO
numbers VALUES (trunc0.99999999. 6));
INSERT 3390699 1
booktown=# SELECT * FROM numbers;
number
10.000000 99999.999999 9.999999
(3 rows)
Типы даты и времени
Таблица 3.14. Типы даты и времени
| Тип данных | Размер | Описание | Интервал | |
| date | 4 байта | Календарная дата (год, месяц и день) | От 4713 г. до н. э. до 32 767 г. н. э. | |
| time | 4 байта | Время суток без часового пояса | От 00:00:00 до 23:59 | :59.99 |
| time with time zone | 4 байта | Время суток с часовым поясом | От 00:00:00+12 до 23:59:59.99-12 |
timestamp с часовым поясом до 2037 г. н. э.
interval 12 байт Общий промежуток От-1780 000 000 лет
времени до 1 780 000 000 лет
Форматы представления даты
Таблица 3.15. Форматы представления даты
| Пример | Описание |
| July 1. 2001 | Название месяца, день и год |
| Sunday July 1. 2001 | Название дня недели, название месяца, день и год |
| July 15. 01 BC | Название месяца, день и год до нашей эры |
| 2001-07-01 | Стандартный формат ISO-8601: год, месяц и день в числовом виде |
| 20010715 | ISO-8601: полный год, месяц, день |
| 010715 | ISO-8601: год из двух цифр, месяц, день |
| 7/01/2001 | Американский формат: месяц, день и год |
| 1/7/2001 | Европейский формат: день, месяц и год |
| 2001.182 | Числовой формат с полным годом и номером дня в году |
Сокращенные обозначения месяцев
Таблица 3.16. Сокращенные обозначения месяцев
| Месяц | Сокращение |
| Январь | Jan |
| Февраль | Feb |
| Март | Mar |
| Апрель | Apr |
| Май | May |
| Июнь | Jun |
| Июль | Jul |
| Август | Aug |
| Сентябрь | Sep, Sept |
| Октябрь | Oct |
| Ноябрь | Nov |
| Декабрь | Dec |
Сокращенные обозначения дней недели
Таблица 3.17. Сокращенные обозначения дней недели
| День | Сокращение |
| Воскресенье | Sun |
| Понедельник | Моп |
| Вторник | Tue, Tues |
| Среда | Wed, Weds |
| Четверг | Thu, Thur, Thurs |
| Пятница | Fri |
| Суббота | Sat |
Примечание 2
Примечание 2
Хотя даты можно форматировать при помощи строковых функций (таких, как to_char()), гораздо эффективнее установить по умолчанию как можно более близкое представление и лишь затем применять ручное преобразование типов и форматирование текста.
Общий формат вывода даты/времени устанавливается применением команды SET к переменной DATESTYLE. Переменной может быть присвоено одно из четырех стандартных значений, перечисленных в табл. 3.18.
Константы форматов даты
Таблица 3.18. Константы форматов даты
| Общий формат | Описание | Пример |
| ISO | Стандарт ISO-8601 | 2001-06-25 12:24:00-07 |
| SQL | Традиционный формат SQL | 06/25/2001 12:24:00.00 РОТ |
| Postgres | Исходный формат PostgreSQL | Моп 25 Jun 12:24:00 2001 PDT |
| German | Региональный формат для Германии | 25.06.2001 12:24:00.00 РОТ |
booktown=# SET DATESTYLE TO SQL;
SET VARIABLE
Если выполнить запрос SELECT current_timestamp после присваивания, PostgreSQL вернет текущее время в формате SQL:
booktown=# SELECT current_timestamp;
timestamp
08/10/2001 13:25:55.00 PDT (1 row)
Вывод текущего значения переменной DATESTYLE во время работы PostgreSQL производится следующей командой:
booktown=# SHOW DATESTYLE;
NOTICE: DateStyle is SQL
with US (NonEuropean)
conventions SHOW VARIABLE
Помимо общих форматов, представление даты в PostgreSQL зависит от другого фактора: порядка перечисления компонентов (табл. 3.19). Этот порядок перечисления определяет, должен ли в выводимой дате день следовать за месяцем или наоборот. Порядок перечисления компонентов применяется к четырем общим форматам знакомой командой SET DATESTYLE и не изменяет в формате ничего, кроме относительного расположения дня и месяца.
Дополнительные форматы вывода даты
Таблица 3.19. Дополнительные форматы вывода даты
| Формат | Описание | Пример |
| European | День/месяц/год | 12/07/2001 17:34:50.00 МЕТ |
| US. NonEuropean | Месяц/день/год | 07/12/2001 17:34:50.0 PST |
Основные действия PostgreSQL
Таблица 3.2. Основные действия PostgreSQL
| Действие | Описание |
| CREATE DATABASE | Создание новой базы данных |
| CREATE INDEX | Создание нового индекса для столбца таблицы |
| CREATE SEQUENCE | Создание новой последовательности в существующей базе данных |
| CREATE TABLE | Создание новой таблицы в существующей базе данных |
| CREATE TRIGGER | Создание нового определения триггера |
| CREATE VIEW | Создание нового представления для существующей таблицы |
| SELECT | Выборка записей из таблицы |
| INSERT | Вставка одной или нескольких новых записей в таблицу |
| UPDATE | Модификация данных в существующих записях |
| DELETE | Удаление существующих записей из таблицы |
| DROP DATABASE | Уничтожение существующей базы данных |
| DROP INDEX | Удаление индекса столбца из существующей таблицы |
| DROP SEQUENCE | Уничтожение существующего генератора последовательности |
| DROP TABLE | Уничтожение существующей таблицы |
| DROP TRIGGER | Уничтожение существующего определения триггера |
| DROP VIEW | Уничтожение существующего представления |
| CREATE USER | Создание в системе новой учетной записи пользователя PostgreSQL |
| ALTER USER | Модификация существующей учетной записи пользователя PostgreSQL |
| DROP USER | Удаление существующей учетной записи пользователя PostgreSQL |
| GRANT | Предоставление прав доступа к объекту базы данных |
| REVOKE | Лишение прав доступа к объекту базы данных |
| CREATE FUNCTION | Создание новой функции SQL в базе данных |
| CREATE LANGUAGE | Создание нового определения языка в базе данных |
| CREATE OPERATOR | Создание нового оператора SQL в базе данных |
| CREATE TYPE | Создание нового типа данных SQL в базе данных |
Примечание 2
Примечание 2
В учебниках SQL термины «команда» и «запрос» часто считаются эквивалентными. В этой книге термин «запрос» используется только по отношению к командам, возвращающим данные (например, SELECT), а не к общим командам SQL, которые также могут создавать и модифицировать данные.
Во внутреннем представлении PostgreSQL структурированные команды SQL интерпретируются в виде последовательности лексем, обычно разделяемых пропусками (пробелами или символами новой строки вне парных ограничителей), хотя некоторые лексемы могут следовать без пропусков, если это не вызывает неоднозначной интеопоетапии (например, опепатопы могут стоять вплотную к идеитификаторам). В данном контексте лексемой считается слово или символ, осмысленно идентифицируемый сервером в процессе разбора (интерпретации) команды SQL.
С технической точки зрения каждая лексема может быть ключевым словом, идентификатором, защищенным идентификатором, константой (также встречается термин «литерал») или одним из специальных символов. К категории ключевых слов PostgreSQL относит слова, имеющие заранее определенный смысл в контексте SQL или PostgreSQL — действия, секции, имена функций и некоторые необязательные составляющие команд SQL (как, например, слово WORK в команде COMMIT). Идентификаторы представляют имена переменных для таблиц, столбцов и других объектов баз данных.
Ключевые слова и идентификаторы относятся к внутренним функциям, значениям и записям, смысл которых определяется PostgreSQL С другой стороны, константы описывают данные, интерпретируемые буквально (например, числа или символьные строки).
Наконец, команды SQL могут содержать специальные символы. К этой категории относятся зарезервированные символы (круглые и квадратные скобки, точка с запятой), влияющие на смысл и расположение ключевых слов, идентификаторов и литералов. Специальные символы можно рассматривать как своего рода «знаки препинания» в командах SQL.
Операторы также относятся к категории специальных символов и используются для применения логических или математических операций между данными (литеральными или представленными в виде идентификаторов). Обычно операторы содержат от одного до четырех символов.
В нескольких ближайших подразделах эти базовые компоненты SQL описываются более подробно.
Taблица 3 20 Форматы представления времени
Taблица 3.20. Форматы представления времени
| Пример | Описание |
| 01:24 | ISO-8601 с точностью до минут |
| 01:24 AM | Эквивалент 01:24 (суффикс AM используется только для наглядности и не влияет на значение) |
| 01:24 РМ | Эквивалент 13:24 (для использования суффикса РМ час должен быть меньше либо равен 12) |
| 13:24 | 24-часовой формат, эквивалент 01:24 РМ |
| 01:24:11 | ISO-8601, с точностью до секунд |
| 01:24:11.112 | ISO-8601, с точностью до микросекунд |
| 012411 | ISO-8601, с точностью до секунд, числовое форматирование |
Допустимые форматы часового пояса
Таблица 3.21. Допустимые форматы часового пояса
| Пример | Описание |
| 01:24:11-7 | ISO-8601, GMT + 7 часов |
| 01:24:11-07:00 | ISO-8601, GMT + 7 часов 0 минут |
| 01:24:11-0700 | ISO-8601, GMT + 7 часов 0 минут |
| 01:24:11 PST | ISO-8601, тихоокеанское стандартное время (GMT + 7 часов) |
Примечание 3
В PostgreSQL поддерживаются все сокращенные обозначения часовых поясов, предусмотренные в стандарте ISO.
Tnntime with time zone поддерживается в PostgreSQL в основном для сохранения совместимости с существующими стандартами SQL и другими СУБД. Если вам потребуется работать с часовыми поясами, рекомендуется использовать тип timestamp, описанный в следующем пункте. Это объясняется прежде всего тем, что из-за действия летнего времени осмысленная интерпретация часовых поясов иногда возможна лишь при наличии даты.
Во внутреннем представлении PostgreSQL вся информация о часовых поясах хранится в виде числового смещения от времени по Гринвичу (GMT), также называемого UTC (Universal Coordinated Time). По умолчанию PostgreSQL выводит время в часовом поясе, заданном в файле конфигурации операционной системы. Если вы хотите, чтобы время выводилось в другом часовом поясе, это можно сделать четырьмя способами.
- Настройка переменной среды TZ на сервере. Переменная используется для определения часового пояса по умолчанию при запуске postmaster. Например, она может задаваться в файле .bash_profile пользователя postgres командой export TZ='zone'.
- Настройка переменной среды PGTZ на стороне клиента. Переменная среды PGTZ может быть прочитана любым клиентом, написанным с использованием библиотеки libpq. Значение интерпретируется как стандартный часовой пояс клиента.
- Команда SQL SET TIMEZONE ТО. Команда устанавливает для текущего сеанса заданный часовой пояс (например, SET TIMEZONE TO UTC).
- Секция SQL AT TIME ZONE. Согласно стандарту SQL92 значение секции задается в виде обозначения часового пояса (например, PST) или интервала (например, Interval ( -07:00')). Секция AT TIME ZONE включается в команду SQL после значения времени (например, SELECT my_t1mestamp AT TIME ZONT 'PST').
Примечание 4
Если переменная часового пояса содержит недопустимое значение, в большинстве систем по умолчанию используется время по Гринвичу (GMT). Кроме того, если при компиляции PostgreSQL был задан ключ USE_AUSTRALIAN_RULES, обозначение EST относится к австралийскому восточному стандартному времени (смещение +10.00 часов по отношению к GMT), а не к восточному стандартному времени США.
Примеры данных типа timestamp
Таблица 3.22. Примеры данных типа timestamp
| Пример | Описание |
| 1980-06-25 11:11-7 | Формат даты ISO-8601 с точностью до минут, часовой пояс PST |
| 25/06/1980 12:24:11.112 | Европейский формат даты с точностью до микросекунд |
| 06/25/1980 23:11 | Американский формат даты с точностью до минут в 24-часовом представлении |
| 25.06.1980 23:11:12 РМ | Немецкий региональный формат даты с точностью до микросекунд и суффиксом РМ |
Хотя в PostgreSQL поддерживается синтаксис создания полей или значений типа timestamp without time zone, в PostgreSQL 7.1.2 полученный тип данных все равно содержит информацию о часовом поясе.
Константы даты и времени
Таблица 3.23. Константы даты и времени
| Константа | Описание |
| current | Текущее (отложенное) время обработки транзакции. В отличие от now не привязывается к конкретному моменту времени и возвращает текущее системное время |
| epoch infinity | 1970-01-01 00:00:00+00 («день рождения» Unix) Абстрактная константа, более «поздняя» по сравнению со всеми допустимыми значениями даты и времени |
| -infinity | Абстрактная константа, более «ранняя» по сравнению со всеми допустимыми значениями даты и времени |
| now | Фиксированное время обработки транзакции |
| today | Полночь текущего дня |
| tomorrow | Полночь следующего дня |
| yesterday | Полночь предыдущего дня |
Если судить только по именам, константы now и current на первый взгляд кажутся идентичными. В действительности они принципиально различаются по способу хранения в таблице. Константа now транслируется в системное время на момент выполнения команды (например, время вставки, если константа используется в команде INSERT). С другой стороны, константа current обычно применяется в особых случаях (например, при отслеживании сведений о процессах) для вычисления разности между начальным временем, зафиксированным константой now, и текущим временем; результат определяет время выполнения процесса. В листинге 3.28 константы now и current используются для построения журнала задач. Первая команда создает таблицу с полями для хранения имени задачи, начальной и конечной даты/времени. В таблице создаются записи двух задач, при этом начальное время задается константой now, а конечное время — константой current. Из листинга видно, что обе задачи не завершены.
ВМИМАНИЕ
Константы даты/времени, как показано в листинге 3.28, обязательно заключаются в апострофы.
Геометрические типы
Таблица 3.24. Геометрические типы
| Тип | Размер | Описание | Синтаксис |
| point | 16 байт | Точечный объект, характеризуемый только координатами на плоскости. Координаты А- и /представляются вещественными числами | (А-./) |
| Iseg | 32 байта | Отрезок прямой. Задается координатами начальной и конечной точек | ((xl.yl). (х2.у2)) |
| box | 32 байта | Прямоугольник. Задается координатами двух углов, расположенных по диагонали | ((xl.yl) лх2.у2)) |
| path | 4+32хлбайт | Замкнутая фигура (аналог многоугольника): множество из п точек, соединенных отрезками | ((xl.yl)....) |
| path | 4+32х/?байт | Разомкнутая фигура (аналог многоугольника): множество из п точек, соединенных отрезками | [(xl.yl),...] |
| polygon | 4+32х/7 байт | Многоугольник (аналог замкнутой фигуры): п конечных точек отрезков, образующих контур многоугольника | ((xl.yl)....) |
| circle | 24 байта | Круг с центром в точке (х.у) и радиусом г | <(х,у) .r > |
Системные поля
Таблица 3.25. Системные поля
| Поле |
Описание |
| old | 4-байтовый уникальный идентификатор объекта записи. В пределах одной таблицы значения end никогда не повторяются |
| tableoid | Идентификатор объекта таблицы, содержащей запись. Имя таблицы связывается с идентификатором в системной таблице рд class |
| xmin | Идентификатор транзакции вставки для кортежа |
| cmin | Идентификатор команды, ассоциированной с транзакцией вставки для кортежа |
| xmax | Идентификатор транзакции удаления для кортежа. Для видимых (не удаленных) кортежей равен нулю |
| cmax | Идентификатор команды, ассоциированной с транзакцией удаления для кортежа. По аналогии с xmax равен нулю для видимых кортежей |
| ctid | Идентификатор, описывающий физическое местонахождение кортежа в базе данных. Поле ctid содержит пару чисел: номер блока и индекс кортежа в блоке |
Таблица authors
Таблица 3.26. Таблица authors
| id | last_name | first_name |
| 1809 | Geisel | Theodor Seuss |
| illl | Denham | Ariel |
| 15990 | Bourgeois | Paulette |
| 2031 | Brown | Margaret Wise |
| 25041 | Margery Williams | Bianco |
| 16 | Alcoa | Louisa May |
| 115 | Poe | Edgar Allen |
Таблица subjects
Таблица 3.27. Таблица subjects
| id | subject | location |
| 1809 | Arts | Creativity St |
| 1111 | Children's Books | Kids Ct |
| 15990 | Classics | Academic Rd |
| 2031 | Computers | Productivity Ave |
| 25041 | Drama | Main St |
| 16 | Horror | Black Raven Dr |
| 115 | Science Fiction | Main St |
Тщательное планирование также помогает избежать ошибок при выборе типов данных. Например, таблица editions связывает коды ISBN с кодами книг, хранящимися в таблице booktown. На первый взгляд кажется, что для представления кодов ISBN можно воспользоваться полем типа integer, однако такое решение было бы ошибочным, поскольку коды ISBN иногда содержат символьные данные. Кроме того, в поле типа integer будут теряться начальные нули (код 0451160916 превратится в 451160916).
Из всего сказанного можно сделать вывод, что проектирование таблиц является важной составляющей процесса проектирования базы данных.
Служебные последовательности
Таблица 3.3. Служебные последовательности PostareSQL в стиле С
| Последовательность | Описание |
| \\ | Обратная косая черта (литерал) |
| V | Апостроф (литерал) |
| \Ь | Забой |
| \f | Подача листа |
| \п | Новая строка |
| \г | Возврат курсора |
| \t | Табуляция |
| \ххх | ASCII-символ с восьмеричным кодом ххх |
Вследствие того что обратная косая черта имеет особый смысл (см. табл. 3.3), при включении в строку этот символ обязательно экранируется другой косой чертой (например, в строке 'A single backslash is: \\' двойной символ обратной косой черты преобразуется в один).
Если две строковые константы PostgreSQL разделены промежутком, в который входит хотя бы один символ новой строки, они объединяются в одну строковую константу. Пример приведен в листинге 3.5.
Представление величин с плавающей точкой
Таблица 3.4. Представление величин с плавающей точкой
| Представление | Пример |
| ##.## | 6.4 |
| ##e[+-]## | 8е-8 |
| [##].##[e[+-]##] | .04e8 |
| ##.[##][e[+-]##] | 4e.5 |
В листинге 3.8 использование всех вещественных форматов продемонстрировано на примере простой команды SQL SELECT.
Синтаксические символы
Таблица 3.5. Синтаксические символы
| Символ | Определение |
| * (звездочка) | Выборка всех полей таблицы в команде SELECT, а также подсчет всех записей в агрегатной функции count () |
| ( ) (круглые скобки) | Группировка выражений, изменение приоритета операторов и вызов функций. Смысл круглых скобок в значительной степени зависит от контекста |
| [ ] (квадратные скобки) | Выборка конкретного элемента массива или объявление типа массива (например, в команде CREATE TABLE) |
| : (точка с запятой) | Признак завершения команды SQL. Внутри команд может использоваться только в строковых константах и защищенных идентификаторах |
| . (запятая) | Разделитель элементов в списке |
| . (точка) | Десятичный разделитель в вещественных константах (например, 3.1415), а также квалификатор имен полей (например, table name. column name) |
| : (двоеточие) | Определение срезов (slices) в массивах |
| $ (знак доллара) | Обозначение позиционного параметра в определении функции |
Основные операторы PostgreSQL
Таблица 3.6. Основные операторы PostgreSQL
| Оператор | Определение |
| Математические операторы | |
| + | Сложение двух чисел |
| - | Вычисление разности двух чисел |
| / | Вычисление частного от деления двух чисел |
| * | Умножение двух чисел |
| ! | Факториал целого числа |
| § | Модуль (абсолютное значение) числа |
| Операторы сравнения | |
| = | Проверка эквивалентности двух величин |
| < | Проверка условия «первое число меньше второго» |
| > | Проверка условия «первое число больше второго» |
| ~ | Поиск совпадения регулярного выражения в тексте |
| Логические операторы |
|
| NOT | Логическое отрицание |
| AND | Логическая конъюнкция (true, если оба логических операнда равны true) |
| OR | Логическая дизъюнкция (true, если хотя бы один из логических операндов равен true) |
Хотя в большинстве выражений оператор = требуется для проверки эквивалентности двух величин, в сочетании с идентификатором в секции SET команды UPDATE он становится оператором присваивания и используется для присваивания нового значения существующему идентификатору.
За дополнительной информацией об операторах обращайтесь к разделу «Операторы» в главе 5.
Простой запрос SQL
Таблица 3.7. Простой запрос SQL
| SELECT | id, name | FROM | states | |
| Тип лексемы | Ключевое слово | Идентификаторы | Ключевое слово | Идентификатор |
| Описание | Команда | Имена полей | Имя секции | Имя таблицы |
Лексемы id, name и states в приведенном примере являются идентификаторами. Идентификаторы Id и name определяют выбираемые поля, а идентификатор states определяет имя таблицы, из которой производится выборка. Таким образом, приведенный выше запрос приказывает PostgreSQL выбрать поля Id и name каждой записи таблицы states. В листинге 3.13 показаны результаты выполнения этого запроса.
Команда UPDATE с секцией SET
Таблица 3.8. Команда UPDATE с секцией SET
| UPDATE | states | SET | id | = | 51 |
| Ключевое слово | Идентификатор | Ключевое слово | Идентификатор | Оператор | Целочисленная константа |
| Команда | Имя таблицы | Имя секции | Имя поля | Присваивание | Новое значение поля id |
Секция WHERE
Таблица 3.9. Секция WHERE
| WHERE | name | = | 'Oregon' |
| Ключевое слово | Идентификатор | Оператор | Строковая константа |
| Имя секции | Имя поля | Проверка эквивалентности | Искомое значение |
Итак, рассмотренная команда UPDATE содержит три ключевых слова, три идентификатора и две константы. Ключевыми словами являются лексемы UPDATE (выполняемое действие), SET (правило обновления записей) и WHERE (критерий отбора обновляемых записей).
Оба оператора представлены знаком =. В секции SET этот знак используется для присваивания (то есть обновления поля существующей записи) — применение, специфическое для секции SET. С другой стороны, в секции WHERE оператор = используется для сравнения двух значений. В данном примере поле name записи сравнивается со строковой константой Oregon.
Наконец, в примере присутствует целочисленная константа 51 (новое значение поля id) и строковая константа Oregon (сравниваемая с полем name в секции WHERE).
Таким образом, команда UPDATE, приведенная в листинге 3.14, обновляет таблицу states, присваивая значение 51 полю Id всех записей, у которых поле name содержит значение Oregon. Результат проверяется следующей командой SELECT.
Таблицы в PostgreSQL
Таблицы в PostgreSQL
Многие программисты (особенно обладающие опытом работы с другими реляционными СУБД на базе SQL) хорошо знакомы с общими концепциями реляционных баз данных, рассмотренными в этой главе. Тем не менее в разных РСУ БД используются разные механизмы работы с таблицами на системном уровне. В этом разделе более подробно описана реализация таблиц в PostgreSQL.
Таблицы
Таблицы
Данный раздел посвящен таблицам — одному из важнейших элементов SQL. Таблицы необходимо знать во всех подробностях, поскольку именно в таблицах хранятся все данные. Хорошее знание логической структуры таблиц является обязательным условием правильного планирования и проектирования структур данных SQL и всех программных функций, обеспечивающих доступ к этим данным.
Таблица состоит из строк (записей) и столбцов (полей), пересечения которых называются элементами данных. В электронных таблицах (например, в Excel) элементам данных соответствуют ячейки таблицы. Столбец определяет имя и тип данных, хранящихся в соответствующем элементе данных записи. Каждая запись (строка таблицы) состоит из элементов данных, описываемых именем и типом соответствующего столбца. Таким образом, каждый элемент данных в записи косвенно связан со всеми остальными элементами этой записи. В определенном смысле поле можно рассматривать как описание отдельного элемента записи, а каждую запись — как совокупность данных, удовлетворяющих этим описаниям.
В табл. 3.1 приведено описание структуры простой таблицы books. Ссылки на эту таблицу будут неоднократно встречаться в дальнейших примерах. В каждой записи таблицы хранится информация об отдельной книге: числовой код книги, название, код автора и код темы. Эти характеристики описываются полями 1 d, ti tl e, authoMd и subjected (слева направо).
Тип money
Тип money
Тип money предназначен для хранения денежных величин и обычных чисел. На момент написания книги тип money считается устаревшим и использовать его не рекомендуется. В книге он представлен лишь как один из действующих типов, который все еще может встречаться в существующих системах PostgreSQL.
Вместо типа money следует использовать тип numeric с масштабом 2 и точностью, достаточной для представления максимальной необходимой величины (включая две цифры для дробной части). Форматирование, аналогичное типу money, выполняется при помощи функции to_char(), используемой в листинге 3.23. В этом примере продемонстрирован оператор конкатенации и функция форматирования текста ltrim(), о которых рассказано в главе 4.
Тип serial
Тип serial
Хотя тип serial не относится к числу стандартных типов, он часто используется при создании в таблице полей-идентификаторов, содержащих уникальное значение для каждой записи. В типе serial объединены функциональные возможности 4-байтового типа integer, индекса и последовательности. В листинге 3.24 тип serial генерирует уникальный идентификатор для каждой записи в таблице auto_identified.
В листинге 3.25 та же задача решается при помощи поля типа integer, функции nextval() и последовательности (последовательности описаны в главе7). На момент написания книги эти два способа были функционально тождественными.
Тип timestamp
Тип timestamp
Тип timestamp PostgreSQL сочетает функциональные возможности типов date и time. Формат timestamp состоит из даты, за которой следует минимум один пробел, после чего идет время и необязательный часовой пояс.
В этом формате поддерживаются любые сочетания форматов даты и времени, перечисленные в табл. 3.15 и 3.20. Примеры допустимого ввода в формате timestamp приведены в табл. 3.22.
Типы данных
Типы данных
SQL относится к категории языков с сильной типизацией. Это означает, что с любым объектом данных, представленным в PostgreSQL, связывается определенный тип, даже если на первый взгляд это и не очевидно. Тип данных одновременно определяет и ограничивает разновидности операций, которые могут выполняться с этими данными.
Типы не только ассоциируются со всеми данными, но и играют важную роль при создании таблиц. Как упоминалось в разделе «Знакомство с реляционными базами данных», таблицы состоят из одного или нескольких полей. При создании таблицы каждому полю, помимо имени, назначается определенный тип данных.
Примечание 1
Примечание 1
Хотя в PostgreSQL предусмотрен достаточно широкий спектр встроенных типов данных, вы также можете определять собственные типы данных командой CREATE TYPE. За дополнительной информацией обращайтесь к описанию команды CREATE TYPE.
В табл. 3.10 перечислены базовые типы данных PostgreSQL, а также их синонимы (альтернативные имена). Также существует множество внутренних (то есть не предназначенных для нормального использования) и устаревших типов данных, которые не приводятся в таблице.
Хотя большинство типов данных PostgreSQL взято непосредственно из стандартов SQL, существуют и другие, нестандартные типы данных (например, гео-
метрические и сетевые типы). По этой причине у типов данных PostgreSQL не всегда находятся прямые аналоги в других СУБД на базе SQL.
Вещественные константы
Вещественные константы
Вещественные константы обладают определенным сходством с целочисленными константами, но используются для представления не только целых, но и дробных величин.
Существует несколько форматов представления вещественных констант, представленных в табл. 3.4. Запись ## означает одну или несколько цифр.
Встроенные константы даты и времени
Встроенные константы даты и времени
В PostgreSQL предусмотрено несколько специальных констант, представляющих стандартные значения даты и времени. Эти константы перечислены в табл. 3.23.
команда SQL состоит из отдельных
Выводы
Итак, команда SQL состоит из отдельных лексем, каждая из которых может быть ключевым словом, идентификатором, защищенным идентификатором, константой или специальным символом. В табл. 3.7 структура команд SQL поясняется на примере простой команды SELECT.
Защищенные идентификаторы
Защищенные идентификаторы
Хотя обычно это и не требуется, идентификаторы могут заключаться в кавычки, указывающие на их буквальную интерпретацию. Например, просмотр всех полей таблицы с именем states обычно производится следующей простой командой:
booktown=# SELECT * FROM states;
id | name | abbreviation
---+-------+---------------
33|Oregon|OR
42| Washington | WA
(2 rows)
Команда содержит ключевые слова SELECT и FROM, а также идентификаторы * (обозначение всех полей) и states (имя таблицы). Команда производит выборку всех полей таблицы states и выводит все ее содержимое.
Аналогичного эффекта можно добиться, заключив идентификатор в кавычки:
booktown=# SELECT * FROM "states";
id | name I abbreviation
33 | Oregon | OR 42 | Washington | WA (2 rows)
Как показывает этот пример, применение кавычек к идентификаторам, записанным символами нижнего регистра, ни на что не влияет. Однако попытка защитить идентификатор stAtes в следующей команде приводит к неудаче:
booktown=# SELECT * FROM "stAtes";
ERROR: Relation 'stAtes' does not exist
Дело в том, что команда приказывает PostgreSQL найти таблицу с именем stAtes (вместо states). Другими словами, заключая идентификатор в кавычки, мы требуем, чтобы интерпретатор PostgreSQL интерпретировал его буквально.
Все незащищенные идентификаторы преобразуются к нижнему регистру. Любая смешанная комбинация символов разных регистров (stAtEs, STATES) при отсутствии кавычек перед выполнением команды автоматически приводится к виду states.
Примечание 1
Примечание 1
Преобразование незащищенных идентификаторов к нижнему регистру является отличительной особенностью PostgreSQL. В соответствии со стандартом SQL92 незащищенные идентификаторы должны преобразовываться к верхнему регистру. По историческим причинам, а также для удобства чтения PostgreSQL не выполняет требования данной части стандарта SQL92. Это обстоятельство особенно важно для администраторов баз данных, знакомых с другими продуктами SQL, в которых идентификаторы автоматически преобразуются к верхнему регистру (например, Oracle). Чтобы ваши приложения легко адаптировались для других платформ, помните о проблеме регистра во избежание конфликтов.
Модуль лексического разбора нормально воспринимает команды, записанные в смешанном регистре (при условии правильности их синтаксиса). Тем не менее к выбору регистра символов при записи программ следует относиться внимательно, поскольку смена регистра символов при оформлении программы может как упростить, так и затруднить чтение большого объема кода SQL.
В этой книге идентификаторы записываются символами нижнего регистра, а ключевые слова — верхнего. Визуальное отделение фиксированных системных синтаксических элементов от пользовательских объектов данных значительно упрощает чтение и понимание сложных команд SQL.
Знакомство с реляционными базами данных
Знакомство с реляционными базами данных
PostgreSQL относится к категории объектно-реляционных систем управления базами данных (ОРСУБД). Модель ОРСУБД представляет собой усовершенствование более традиционной модели реляционной системы управления базами данных (РСУБД). В РСУБД логически связанные данные хранятся в двумерных структурах, называемых таблицами. Данные могут состоять из элементов, относящихся к различным стандартным типам — целые и вещественные числа, символы, строки, дата/время. В таблице элементы данных образуют «решетку» из столбцов (полей) и строк (записей). Одной из главных особенностей реляционной модели является ее концептуальная простота, причем это может считаться как ее главным достоинством, так и главным недостатком.
Объектно-реляционная специфика PostgreSQL дополняет традиционную реляционную модель данных многочисленными усовершенствованиями. К их числу относится поддержка массивов (хранения нескольких элементов в одном поле), наследования (связей типа «предок—потомок» между таблицами) и функций (программных методов, вызываемых командами SQL). Для опытных программистов в PostgreSQL даже предусмотрены возможности расширения типов данных и использования процедурных языков.
Вследствие объектно-реляционной ориентации таблицы иногда называются классами, а записи и поля могут соответственно именоваться экземплярами (instances) и атрибутами (attributes). В книге эти термины считаются синонимами. Другие структуры данных SQL (такие, как индексы и представления) иногда называются объектами базы данных.
Примечание 1
Примечание 1
Учтите, что термин «объектно-реляционный» не является синонимом термина «объектно-ориентированный», характерного для многих современных языков программирования. Несмотря на поддержку ряда объектных усовершенствований, PostgreSQL все равно формально является реляционной системой управления базами данных (РСУБД).
Знакомство с SQL
Знакомство с SQL
SQL (Structured Query Language) — мощный, универсальный и проверенный временем язык запросов к реляционным базам данных. История SQL восходит к научным разработкам компании IBM в 70-х годах. В нескольких ближайших разделах вы познакомитесь с историей языка SQL, его предшественниками и различными стандартами SQL, появившимися за эти годы.
SQL в PostgreSQL
Анализ структуры таблицы
Анализ структуры таблицы
Команда \d (с указанием имени таблицы) предназначена для вывода структуры таблицы и ее ограничений, если они имеются. В листинге 4.7 приведены выходные данные команды \d для таблицы books, созданной в предыдущем разделе.
Обратите внимание: каждая строка результата описывает одно из полей (то есть столбцов) таблицы; таким образом, таблица фактически разворачивается па 90°. Такое представление выбрано для наглядности, поскольку многие таблицы содержат большое количество полей, не помещающихся на экране (или на печатной странице) по горизонтали. В книге этот формат будет использоваться при описании структуры таблиц.
COPY TO
COPY TO
Синтаксис команды COPY FROM практически аналогичен синтаксису команды, предназначенной для экспортирования данных в файл, просто ключевое слово FROM заменяется ключевым словом ТО. Кроме того, ключевое слово stdin заменяется ключевым словом stdout, если выходные данные вместо файла направляются в стандартный вывод (например, на экран в psql). В листинге 4.22 приведен пример экспортирования таблицы books в ASCII-файл.
Добавление данных командами INSERT и COPY
Добавление данных командами INSERT и COPY
После создания таблицы с заданной структурой наступает следующий этап — заполнение таблицы данными. В PostgreSQL имеются три общих способа заполнения таблиц данными:
- вставка новых группированных данных командой INSERT INTO;
- вставка существующих данных из другой таблицы командой INSERT INTO в сочетании с командой SELECT;
- вставка данных из внешнего файла командой COPY (или \copy).
Добавление ограничений
Добавление ограничений
После создания таблицы сохраняются некоторые возможности добавления ограничении. В PostgreSQL 7.1.x команда ALTER TABLE с секцией ADD CONSTRAINT позволяет определять для полей существующих таблиц только ограничения внешнего ключа и проверки. Команда создания новых ограничений имеет следующий синтаксис:
ALTER TABLE таблице
ADD CONSTRAINT имя_ограничения определение
Синтаксис определения зависит от типа ограничения. В листинге 4.12 продемонстрирован синтаксис создания ограничения внешнего ключа для таблицы editions (связанной с полем id таблицы books) и ограничения проверки для поля type.
Другие возможности SQL
Другие возможности SQL
В этой главе были представлены фундаментальные концепции применения языка SQL в PostgreSQL. В частности, были рассмотрены вопросы создания таблиц и выполнения с ними различных операций, включая выборку и модификацию данных. В главе 5 будут подробно описаны функции и операторы PostgreSQL, многие из которых уже встречались в этой главе.
Двоичный формат
Двоичный формат
Команда COPY также позволяет выполнять операции ввода и вывода с данными в двоичном формате. Если команда COPY FROM содержит ключевое слово BINARY, входной файл должен быть создан командой COPY TO в двоичном формате PostgreSQL. Двоичные файлы загружаются быстрее ASCII-файлов, но в отличие от последних их нельзя читать и редактировать в простых текстовых редакторах.
В листинге 4.21 приведена команда COPY, предназначенная для вставки записей из двоичного файла в таблицу subjects базы данных booktown.
Группировка записей
Группировка записей
Секция GROUP BY представляет чрезвычайно мощную концепцию SQL — агрегирование. На практике агрегирование запросов SQL приводит к тому, что все записи с одинаковыми значениями выражения, заданного в секции GROUP BY, группируются в одну агрегатную запись. Выражение GROUP BY может быть простым полем таблицы, но оно также может представлять собой произвольную операцию с полем. При перечислении нескольких полей или выражений, разделенных запятыми, группировка записей осуществляется лишь при совпадении записей по всем критериям.
Чтобы эффективно пользоваться агрегированием, необходимо понимать, что все целевые поля, участвующие в агрегирующем запросе, но не указанные в секции GROUP BY, доступны лишь при выборке через агрегатную функцию. Агрегатная функция получает имя поля (или выражение, в котором участвует хотя бы одно имя поля), представляющее несколько значений (например, в нескольких сгруппированных записях), выполняет с ними некоторую операцию и возвращает одно значение.
Самые распространенные агрегатные функции:
- count () — возвращает количество записей в наборе;
- тах () — возвращает максимальное значение в наборе;
- min () — возвращает минимальное значение в наборе.
Предположим, вы хотите вывести количество книг, хранящихся в базе данных booktown для каждого издательства. Название издательства связывается с названиями опубликованных книг простым объединением таблиц editions и publishers, однако подсчитывать записи вручную весьма утомительно, а при очень больших объемах итоговых наборов — вообще неприемлемо.
В листинге 4.40 выполняется стандартное объединение двух таблиц базы данных booktown, но в нем присутствуют два новых элемента: вызов функции count () и секция GROUP BY.
Использование таблиц
Использование таблиц
Таблицы являются основными блоками хранения данных в базе. Перед любыми операциями создания, выборки или модификации записей необходимо сначала создать таблицу, в которой эти записи будут храниться.
В этом разделе рассматриваются процедуры создания, модификации и удаления таблиц командами CREATE TABLE, ALTER TABLE n DROP TABLE SQL (вопросам создания баз данных посвящена глава 9).
Конструкции CASE
Конструкции CASE
Чтобы программа SQL могла принимать простейшие решения, не прибегая к процедурным языкам, в PostgreSQL поддерживаются конструкции CASE, предусмотренные стандартом SQL Ключевые слова SQL CASE, WHEN, THEN и END позволяют выполнять простые условные преобразования записей.
Вся конструкция CASE включается в целевой список команды SELECT. По умолчанию итоговому полю конструкции CASE присваивается имя case, но ему можно назначить синоним, как любому обычному полю. Общий синтаксис конструкции CASE в списке целей команды SELECT выглядит следующим образом:
CASE WHEN условие! THEN результат! WHEN условие2 THEN результат2
[ ... ]
[ ELSE результат_по_умопчанию END [ AS синоним ]
Конструкция CASE-WHEN-THEN-ELSE отчасти напоминает условные команды f-then-else в традиционных языках программирования (листинг 4.50). Условия секций WHEN должны возвращать логический результат.
Если условие в секции WHEN выполняется, результат соответствующей секции THEN возвращается в поле итогового набора. Если ни одно условие не выполнено, можно задать значение по умолчанию в секции ELSE. Если при отсутствии секции ELSE результат остается неопределенным, возвращается NULL.
Копирование данных из внешних файлов командой COPY
Копирование данных из внешних файлов командой COPY
В PostgreSQL поддерживается и такая полезная возможность, как прямое импортирование данных в таблицу из внешних файлов командой COPY. Файл, содержащий входные данные команды COPY, хранится либо в стандартном текстовом формате ASCII с ограничением полей специальным символом-разделителем, либо в двоичном формате таблиц PostgreSQL. В ASCII-файлах в качестве разделителя обычно используется символ табуляции или запятая. При импортировании данных из ASCII-файла каждая строка файла интерпретируется как отдельная запись данных, а каждый компонент строки — как значение соответствующего поля записи.
Команда COPY FROM работает значительно быстрее обычной команды INSERT, поскольку данные передаются прямо в приемную таблицу за одну транзакцию. С другой стороны, к формату исходного файла предъявляются чрезвычайно жесткие требования, поэтому ошибка всего в одной строке приводит к сбою всей команды COPY.
Синтаксис команды COPY FROM:
COPY [ BINARY ] таблица [ WITH 0IDS ]
FROM { 'имя_файла' \ stdin }
[ [USING] DELIMITERS 'разделитель' ]
[ WITH NULL AS 'строка_nulГ ]
Ниже поясняется смысл параметров команды.
- BINARY. Признак импортирования входных данных из двоичного файла, ранее созданного командой COPY TO.
- таблица. Имя таблицы, в которую импортируются данные.
- WITH OIDS. Из первой строки файла загружаются значения всех идентификаторов OID импортируемой таблицы.
- FROM { 'имя_файла' \ stdin }. Источник, из которого PostgreSQL получает входные данные — файл с заданным именем либо стандартный ввод (stdin).
- [ USING ] DELIMITERS 'разделитель'. Символ, используемый в качестве разделителя при разборе входных данных. Не используется для файлов, выведенных в двоичном формате PostgreSQL.
- WITH NULL AS ' строка_null. Заданная строка должна интерпретироваться как значение NULL. He используется для файлов, выведенных в двоичном формате PostgreSQL.
При работе с входными файлами в формате ASCII в секции DELIMITERS передается символ, используемый в качестве разделителя значений полей в строках файла. Если разделитель не указан, PostgreSQL считает, что значения разделяются символом табуляции. Необязательная секция WITH NULL определяет формат, в котором передаются значения NULL. Если секция отсутствует, PostgreSQL интерпретирует последовательность \N как NULL (например, пустые поля исходного файла по умолчанию интерпретируются как пустые строковые константы, а не как NULL).
Если данные вводятся вручную или передаются терминалу другой программой, в качестве источника в секции FROM можно указать стандартный ввод (stdin). При получении данных из стандартного ввода входной поток должен завершаться последовательностью \. (обратная косая черта плюс точка), за которой немедленно следует символ новой строки.
В листинге 4.19 приведено содержимое файла, выведенного PostgreSQL в формате ASCII. Поля разделяются запятыми, а для представления NULL используется строка \null.B файле сохранены данные из таблицы subjects базы данных booktown.
Назначение системного пути для psql
Листинг 4.1. Назначение системного пути для psql
[user@host user]$ psql
bash: psql: command not found
[user@host user]$ echo $PATH
/b1n:/usr/bin:/usr/local/bin:/usr/bin/Xll:/usr/XHR6/tnn
[user@host user]$ export PATH=$PATH:/usr/local/pgsql/bin
[user@host user]$ psql testdb
Welcome to psql. the PostgreSQL interactive terminal.
Type: \copyright for distribution terms \h for help with SQL commands \? for help on internal slash commands \g or terminate with semicolon to execute query \q to quit
testdb=#
После настройки переменной PATH интерактивный терминал PostgreSQL запускается командой psql, за которой следует имя базы данных.
ВНИМАНИЕ
После выхода из psql изменения переменной среды будут потеряны. Чтобы изменения переменной PATH сохранялись после выхода из программы, команда настройки PATH включается в стартовый сценарий командного интерпретатора (например, ~/.bash_profile).
относящийся к интерпретатору
Листинг 4.1, относящийся к интерпретатору bash, иллюстрирует процедуру назначения системного пути для клиента psql.
Переименование таблицы
Листинг 4.10. Переименование таблицы
oktown=# ALTER TABLE books RENAME TO literature;
TER
oktown=# ALTER TABLE literature RENAME TO books;
TER
Переименование поля
Листинг 4.11. Переименование поля
booktown=# \d daily_inventory
Table "daily_inventory"
Attribute | Type | Modifier
isbn | text
in_stock | boolean |
booktown=# ALTER TABLE daily_inventory
booktown-# RENAME COLUMN in_stock TO is_in_stock;
ALTER
booktown=# ALTER TABLE daily_inventory
booktown-l RENAME COLUMN is_in_stock TO is_stocked;
ALTER
Создание новых ограничений
Листинг 4.12. Создание новых ограничений в существующей таблице
booktown=# ALTER TABLE editions
booktown-# ADD CONSTRAINT foreign_book
booktown-# FOREIGN KEY (book_id) REFERENCES books (id);
NOTICE: ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s)
for FOREIGN KEY check(s)
CREATE
booktown=# ALTER TABLE editions
booktown-# ADD CONSTRAINT hard_or_paper_back
booktown-# CHECK (type = 'p' OR type = 'h'):
ALTER
Установка ограничения внешнего ключа приводит к тому, что любое значение book_i d в таблице edi ti ons также должно существовать в таблице books. Кроме того, вследствие установленного ограничения проверки поле type в таблице editions может содержать только значения р или Ь.
Примечание 2
Примечание 2
Ограничение уникальности также неявно устанавливается при создании уникального индекса командой CREATE INDEX (см. раздел «Индексы» в главе 7).
Дополнительная информация об ограничениях, их назначении и синтаксисе приведена в главе 7.
Смена владельца таблицы
Листинг 4.13. Смена владельца таблицы
booktown=# ALTER TABLE employees booktown-# OWNER TO corwin;
ALTER
Примечание 3
Примечание 3
Смена владельца таблицы может осуществляться либо текущим владельцем, либо суперпользователем PostgreSQL.
Реструктуризация
Листинг 4.14. Реструктуризация таблицы командой CREATE TABLE AS
booktown=# \d books
Table "books" Attribute | Type | Modifier
id | integer | not null
title text I not null
authorjd | integer |
subjectjd integer j
publication j date | Index: books_id_pkey
booktown=# CREATE TABLE new_books
booktown-# (id, title. authorjd, subjectjd)
booktown-# AS SELECT id, title, authorjd, subjectjd
booktown-f FROM books;
SELECT
booktown=# ALTER TABLE books RENAME TO old_books;
ALTER
booktown=# ALTER TABLE new_books RENAME TO books;
ALTER
booktown=# \d books
Table "books" Attribute | Type | Modifier
id | integer |
title | text |
authorjd j integer j
subjectjd | integer |
booktown=# DROP TABLE books;
DROP
ВНИМАНИЕ
В PostgreSQL 7.1.x присутствие в команде SELECT необязательного списка полей, заключенного в круглые скобки, исключает использование специального символа *. Недостаток должен быть исправлен в PostgreSQL 7.2.
Реструктуризация
Листинг 4.15. Реструктуризация таблицы командами CREATE TABLE и INSERT INTO
booktownHf CREATE TABLE new_books (
booktown(# id integer UNIQUE,
booktown(# title text NOT NULL.
booktown(# authorjd integer.
booktown(# subjectjd integer.
booktown(# CONSTRAINT books_id_pkey PRIMARY КЕУ (id)
booktown(# ):
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index ' books Jd_pkey'
for table 'new_books'
CREATE
booktown=# INSERT INTO new_books
booktown-# SELECT id, title, author_id, subjectjd
booktown-f FROM books;
INSERT 0 12
booktown=# ALTER TABLE books RENAME TO old_books;
ALTER
booktown=# ALTER TABLE new_books RENAME TO books:
ALTER
booktown=# \d books
Table "books" Attribute | Type | Modifier
id | integer | not null
title ( text I not null
authorjd integer j
subjectjd integer | Index: booksjd_pkey
За дополнительной информацией об использовании команды INSERT INTO с командой SELECT обращайтесь к подразделу «Вставка данных из других таблиц командой SELECT» раздела «Добавление данных командами INSERT и COPY». Команда SELECT рассматривается в разделе «Выборка данных командой SELECT».
Вставка новой записи в таблицу books
Листинг 4.16. Вставка новой записи в таблицу books
booktown=# INSERT INTO books (Id, title, author_id, subject_id)
booktown-# VALUES (41472, 'Practical PostgreSQL', 1212, 4);
INSERT 3574037 1
Команда SQL, приведенная в листинге 4.16, вставляет новую запись с кодом (id) 41472, названием «Practical PostgreSQL», кодом автора 1212 и кодом темы 4. Обратите внимание на завершающее сообщение, начинающееся со слова INSERT, — оно указывает на то, что операция вставки была выполнена успешно. Первое число после INSERT является идентификатором объекта (OID) созданной записи, а второе число обозначает количество созданных записей (в нашем примере,— 1).
В приведенном примере необязательный список полей совпадает с порядком следования полей в структуре таблицы (слева направо). В данном случае этот список можно опустить, поскольку команда INSERT предполагает, что значения присваиваются в естественном порядке следования полей таблицы. Поля в списке можно переставить, но в этом случае порядок значений в секции VALUES тоже должен измениться, как показано в листинге 4.17.
Изменение порядка перечисления полей
Листинг 4.17. Изменение порядка перечисления полей
booktown=# INSERT INTO books (subjected, author_id, id, title)
booktown-# VALUES (4, 7805, 41473, 'Programming Python');
INSERT 3574041 1
Вставка данных из другой таблицы
Листинг 4.18. Вставка данных из другой таблицы
booktown-# INSERT INTO books (id, title, author_id, subject_id)
booktown-# SELECT nextval('book_ids', title, author_id, subject_id
booktown-# FROM book_queue WHERE approved;
INSERT 0 2
В приведенном примере запрос SELECT, включенный в команду INSERT INTO, переносит две записи из таблицы book_queue в таблицу books. В этом контексте допускается использование любой синтаксически правильной команды SELECT. В нашем примере в выборку включается результат вызова функции nextval () для последовательности bookj ds, за которым следуют значения полей title, author_id и subject_id из таблицы book_queue.
На этот раз команда создает сразу несколько новых записей, поэтому в сообщении об успешном выполнении операции вместо значения OID, которое выводилось бы при вставке одной записи, выводится 0. Второе число, как и в случае с обычной командой INSERT INTO, равно количеству созданных записей (в данном случае — 2).
Пример копируемого ASCIIфайла
Листинг 4.19. Пример копируемого ASCII-файла
1.Business.Productivity Ave
2.Children's Books,Kids Ct
3.Classics.Academic Rd
4,Computers,Productivity Ave
5,Cooking.Creativity St
12.Religion.\null
8.Hi story.Academic Rd
9.Horror.Black Raven Dr
10.Mystery.Black Raven Dr
11.Poetry.Sunset Dr
13.Romance.Main St
14.Science.Productivity Ave
15.Science Fiction.Main St
0.Arts.Creativity St
6.Drama.Main St
7.Entertainment.Main St
Следующая команда (листинг 4.20) импортирует содержимое файла /tmp/ subjects.sql в таблицу subjects базы данных booktown.
Получение списка команд psql booktown=# \?
Листинг 4.2. Получение списка команд psql booktown=# \?
\а toggle between unaligned and aligned mode
\c[onnect] [dbname|- [user]]
connect to new database (currently 'booktown')
\C
table title
\copy... perform SQL COPY with data stream to the client machine
\copyright show PostgreSQL usage and distribution terms
\d
| Поле | Тип | Модификатор |
| id | integer | NOT NULL DEFAULT nextval ( 'shipments_ship_id_seq' ) |
| customer_id | integer | |
| isbn | text | |
| ship_date | timestamp |
booktown=# SELECT COUNT(*) FROM shipments;
count
32
(1 row)
Звездочка (*) в этом запросе просто указывает PostgreSQL на необходимость эдсчета всех записей вместе со значениями NULL, которые могли бы присутствоваъ в поле с явно заданным именем. Запрос подсчитывает общее количество записей, то есть количество зарегистрированных поставок.
Предположим, данные из таблиц editions и books были объединены секцией JOIN, чтобы в выходные данные входили названия всех книг. Более того, в запрос была включена секция GROUP BY, обеспечивающая группировку поставок по названиям книг.
Вспомните, о чем говорилось выше в этой главе, — при группировке по полю title функция count() подсчитывает количество записей в каждой группе (в данном случае — для каждого названия книги). Наконец, для поля ship_date таблицы shipments вызывается функция max(), чтобы в результатах запроса выводилась дата последней поставки по каждой книге и количество экземпляров:
booktown=# SELECT count(*) AS num_shipped, max(ship_date), title
booktown-# FROM shipments
booktown-# JOIN editions USING (isbn)
booktown-# NATURAL JOIN books AS b (book_id)
booktown-# GROUP BY b.title
booktown-# ORDER BY num_shipped DESC;
num_shipped | max | title
5 | 2001-08-13 09:47:04-07 | The Cat in the Hat
5 | 2001-08-14 13:45:51-07 | The Shining
4 | 2001-08-11 09:55:05-07 | Bartholomew and the Oobleck
3 | 2001-08-14 13:49:00-07 | Franklin in the Dark
3 | 2001-08-15 11:57:40-07 | Goodnight Moon
3 | 2001-08-14 13:41:39-07 | The Tell-Tale Heart
2 | 2001-08-15 14:02:01-07 | 2001: A Space Odyssey
2 | 2001-08-14 08:42:58-07 | Dune
2 | 2001-08-07 13:00:48-07 | Little Women
2 | 2001-08-09 09:30:46-07 | The Velveteen Rabbit
1 | 2001-08-14 07:33:47-07 | Dynamic Anatomy
(11 rows)
Запрос выдает полезную информацию, но синтаксис получается слишком громоздким, и часто вводить его вручную нежелательно. В листинге 4.62 показано, как на базе этого запроса создать представление командой CREATE VIEW.
Удаление дубликатов и ключевое слово DISTINCT
Удаление дубликатов и ключевое слово DISTINCT
Необязательное ключевое слово DISTINCT исключает дубликаты из итогового набора. Если ключевое слово ON отсутствует, из результатов запроса с ключевым словом DISTINCT исключаются записи с повторяющимися значениями целевых полей. Проверяются только поля, входящие в целевой список SELECT.
Предположим, таблица books содержит 15 записей, в каждой из которых присутствует поле authorjd. Некоторые коды авторов многократно встречаются в таблице books. Включение в запрос ключевого слова DISTINCT (листинг 4.31) гарантирует, что итоговый набор будет содержать не более одной записи для каждого автора.
Удаление таблиц командой DROP TABLE
Удаление таблиц командой DROP TABLE
В SQL таблицы удаляются командой DROP TABLE. Команда имеет следующий синтаксис (таблица — имя удаляемой таблицы):
DROP TABLE таблица
Использование команды DROP TABLE требует осторожности, поскольку удаление таблицы приводит к уничтожению всех хранящихся в ней данных.
Примечание 4
Примечание 4
Уничтожение таблицы с неявно созданным индексом приводит к уничтожению всех связанных с ней индексов.
Удаление записей командой DELETE
Удаление записей командой DELETE
Удаление записей из таблиц производится стандартной командой SQL DELETE. Вызов DELETE приводит к необратимым последствиям (исключение составляют тщательно спланированные транзакционные блоки), поэтому удаление данных из базы требует крайней осторожности.
Команда удаления одной или нескольких записей из базы имеет следующий синтаксис:
DELETE FROM [ ONLY ] таблица [ WHERE условие ]
- DELETE FROM [ ONLY ] таблица. Ключевое слово ONLY означает, что обновляется только заданная таблица, но не ее производные таблицы. Применяется лишь в том случае, если таблица использовалась в качестве базовой при наследовании.
- WHERE условие. В секции WHERE задается критерий, по которому в таблице выбираются удаляемые записи. При отсутствии секции WHERE из таблицы удаляются все записи.
Перед выполнением команды DELETE рекомендуется выполнить команду SELECT с соответствующей секцией WHERE и просмотреть удаляемые данные перед их фактическим уничтожением. Пример приведен в листинге 4.57.
Уничтожение представлений
Уничтожение представлений
Команда уничтожения представления имеет следующий синтаксис (представление — имя уничтожаемого представления):
DROP VIEW представление
Уничтожение представления не отражается на данных, которые использовались представлением. Представление всего лишь обеспечивает доступ к данным других таблиц и потому может уничтожаться без потери данных (хотя запрос, на котором оно основано, конечно, теряется).
Уточнение запросов
Уточнение запросов
В секции WHERE задается логическое условие, которому должны удовлетворять записи итогового набора. На практике команда SELECT почти всегда содержит как минимум одну уточняющую секцию WHERE.
Предположим, вы хотите получить список всех книг о компьютерных технологиях в базе данных booktown. У этих книг поле subject_id равно 4. Соответственно в секцию WHERE включается оператор =, который проверяет это условие. Пример приведен в листинге 4.32.
Внешние объединения
Внешние объединения
С другой стороны, внешнее объединение может сохранить записи, для которых не находится соответствия в других наборах. В этом случае недостающие поля заполняются значениями NULL. Решение о том, войдет ли такая запись во внешнее объединение, зависит от того, в каком из объединяемых наборов отсутствуют данные, и от типа внешнего объединения.
Существуют три разновидности внешних объединений.
- Левое внешнее объединение. Всегда содержит как минимум один экземпляр каждой записи из набора, указанного слева от ключевого слова JOIN. Отсутствующие поля из правого набора заполняются значениями NULL.
- Правое внешнее объединение. Всегда содержит как минимум один экземпляр каждой записи из набора, указанного справа от ключевого слова JOIN. Отсутствующие поля из левого набора заполняются значениями NULL.
- Полное внешнее объединение. Всегда содержит как минимум один экземпляр каждой записи каждого объединяемого набора. Отсутствующие поля в записях нового набора заполняются значениями NULL.
Допустим, вы хотите получить информацию о каждой книге вместе со всеми имеющимися кодами ISBN. Запрос с внутренним объединением таблиц books и editions вернет набор данных с названиями книг и кодами ISBN, но, как видно из листинга 4.38, если у книги нет печатного издания (или информация об этом издании еще не занесена в базу данных booktown), информация о ней не включается в результат.
Вторая команда в листинге 4.38 использует внешнее объединение и возвращает 20 записей. У трех записей в итоговом наборе отсутствуют коды ISBN, но эти записи все равно включаются в результат.
Внутренние и внешние объединения
Внутренние и внешние объединения
На практике чаще используются внутренние и внешние объединения, при которых секция JOIN обязательно содержит критерий, уточняющий связи между объединяемыми наборами данных. Синтаксис внутренних и внешних объединений:
источник! [ NATURAL ] тип_объединения источник2
[ ON ( условие [. ...] ) I USING ( поле [, ...] ) ]
- источник! Первый из объединяемых наборов данных (имя таблицы или подзапрос).
- [ NATURAL ]. Два набора данных объединяются по равным значениям одноименных полей (например, если обе таблицы содержат поле с именем id, то объединяются записи с совпадающими значениями полей id). При наличии ключевого слова NATURAL учитываются синонимы полей (если они были назначены), а секции ON и USING становятся не только ненужными, но и недопустимыми.
- тип_объединепия. В данном контексте допустимы следующие типы объединений: [INNER] JOIN (то есть JOIN без уточнения подразумевает INNER JOIN), LEFT [OUTER] JOIN, RIGHT [OUTER] JOIN и FULL [OUTER] JOIN.
- источник2. Второй из объединяемых наборов данных (имя таблицы или подзапрос).
- ON ( условие [. ... ] ). Отношение между источниками. В секции ON можно задать произвольный критерий по аналогии с тем, как задаются условия в секции WHERE. В критерии могут использоваться синонимы таблиц и полей.
- USING ( поле [, ... ]). Одноименные поля источников, по совпадающим значениям которых производится объединение. В отличие от NATURAL JOIN позволяет ограничиться некоторыми одноименными полями, тогда как NATURAL проводит объединение по всем одноименным полям. По аналогии с NATURAL в параметрах секции USING учитываются синонимы полей.
Внутренние объединения
Внутренние объединения
Конструкция INNER JOIN была включена в стандарт SQL92 для того, чтобы условия объединения источников данных (условия JOIN) можно было отличить от условий принадлежности записей к итоговому набору (условия WHERE). Рассмотрим две команды SELECT, приведенные в листинге 4.36.
Вставка данных из других таблиц командой SELECT
Вставка данных из других таблиц командой SELECT
Команда INSERT INTO применяется и в другой ситуации — когда данные, сохраняемые в таблице, уже присутствуют в другой таблице (или неекольких таблицах). В этом случае команда имеет следующий синтаксис:
INSERT INTO таблица
[ ( имя_поля [. ...] ) ] запрос
По аналогии с синтаксисом INSERT INTO, представленным в предыдущем подразделе, команда содержит необязательный список полей, которым присваиваются новые значение. Тем не менее в этой форме INSERT INTO секция VALUES заменяется полной командой SQL SELECT.
Предположим, база данных booktown содержит таблицу book_queue с информацией о книгах, ожидающих поступления в продажу. После подтверждения данные переносятся из таблицы book_queue в обычную таблицу books. Пример решения этой задачи продемонстрирован в листинге 4.18.
Вставка новых данных
Вставка новых данных
Ниже приведен синтаксис команды INSERT INTO при вставке новых данных:
INSERT INTO таблица
[ ( имя_поля [, ...] ) ] VALUES ( значение [. ...] )
Ниже перечислены параметры команды.
- таблица. Имя таблицы, в которую вставляются данные командой SQL INSERT.
- ( имя_поля [. ...] ). Необязательный группированный список полей новой записи, которым присваиваются значения.
- VALUES. Ключевое слово SQL, за которым следует группированный список значений.
- ( значение [, ... ] ). Обязательный группированный список значений полей. Для каждого поля указывается ровно одно значение, элементы списка разделяются запятыми. Элемент списка может быть выражением (например, операцией с двумя операндами) или константой.
В листинге 4.16 приведен пример создания новой записи в таблице books базы данных booktown.
Ввод запросов в приглашении psql
Ввод запросов в приглашении psql
Запустите psql и убедитесь в том, что вы подключены к нужной базе данных (и зарегистрированы в системе с нужными параметрами). На экране появляется приглашение, которое по умолчанию совпадает с именем текущей базы данных. Приглашение выглядит примерно так:
testdb=#
Чтобы передать PostgreSQL команду SQL, просто введите ее в приглашении. Весь вводимый текст накапливается до тех пор, пока ввод не будет завершен символом точки с запятой (:). Ввод команды не прерывается даже разрывами строк,
что позволяет распределить запрос по нескольким строкам. Пример многострочного запроса приведен в листинге 4.3.
Выбор интервалов записей
Выбор интервалов записей
В PostgreSQL количество записей, выбираемых запросом SQL, не ограничивается. Обработка запроса, возвращающего несколько миллионов записей, займет много времени, но сервер не остановится, пока не вернет весь итоговый набор (или процесс не будет прерван извне).
Вероятно, выделение некоторой части выборки легко реализуется на программном уровне, но в SQL предусмотрены ключевые слова LIMIT и OFFSET, упрощающие выборку заданной части итогового набора.
Секция LIMIT ограничивает максимальное количество записей в итоговом наборе (хотя размер итогового набора вполне может быть меньше заданной величины). При наличии секции OFFSET в итоговом наборе пропускается количество записей, заданное параметром секции. Если заданы оба ключевых слова, то отсчет ограничения, указанного в секции LIMIT, начинается после пропуска записей в соответствии с секцией OFFSET.
Как показано в листинге 4.45, первый запрос, содержащий простую секцию LIMIT, ограничивается выборкой первых пяти записей из результатов объединения таблиц editions и books. Обычно это объединение содержит 17 записей.
Выбор источников в секции FROM
Выбор источников в секции FROM
В секции FROM указывается источник данных — таблица или итоговый набор. Секция может содержать несколько источников, разделенных запятыми. Результат подобного перечисления функционально эквивалентен перекрестному объединению, о котором рассказано в подразделе «Объединение наборов данных».
Использование нескольких источников данных в PostgreSQL требует осторожности. В результате выполнения команды SELECT для нескольких источников без секций WHERE и JOIN, уточняющих связи между источниками, возвращается полное декартово произведение источников. Иначе говоря, итоговый набор содержит все возможные комбинации записей из всех источников.
Обычно для уточнения связей между источниками, перечисленными через запятую в секции FROM, используется секция WHERE. Пример приведен в листинге 4.27 (за дополнительной информацией о секции WHERE обращайтесь к подразделу «Уточнение запросов»).
Выбор полей
Выбор полей
Команда SELECT * является хорошим примером простейшего запроса, но на прак-гике необходимая информация нередко ограничивается несколькими полями габлицы. Чтобы повысить эффективность выборки и сделать запрос более наглядным, рекомендуется явно перечислить все необходимые поля вместо полной вы-эорки с символом *. В частности, ограничение выборки особенно актуально при использовании секции JOIN, подробно рассматриваемой ниже в подразделе «Объединение наборов данных».
Поля, включаемые в итоговый набор, перечисляются после ключевого слова SELECT. Запрос возвращает данные только для полей, входящих в этот список. По-эядок перечисления полей не обязан совпадать с их порядком в структуре табли-ды; допускается как многократное вхождение, так и отсутствие некоторых полей в :писке. Пример приведен в листинге 4.24.
Выборка данных командой SELECT
Выборка данных командой SELECT
Центральное место в SQL занимает команда SELECT, предназначенная для построения запросов и выборки данных из таблиц и представлений. Данные, возвращаемые в результате запроса, называются итоговым набором; как и таблицы, они состоят из записей и полей.
Данные итогового набора не хранятся на диске в какой-либо постоянной форме. Итоговый набор является лишь временным представлением данных, полученных в результате запроса. Структура полей итогового набора может соответствовать структуре исходной таблицы, но может и радикально отличаться от нее. Итоговые наборы даже могут содержать поля, выбранные из других таблиц.
Из-за своей особой роли в PostgreSQL команда SELECT также является самой сложной командой, обладающей многочисленными секциями и параметрами. Ниже приведено общее определение синтаксиса SELECT, а отдельные компоненты рассматриваются в следующих разделах. Термин выражение соответствует имени поля или общему выражению (например, результату операции, в которой участвует значение поля и константа или значения двух полей).
SELECT [ ALL | DISTINCT [ ON ( выражение [. ...] ) ] ] цель [ AS имя ] [. ...] [ FROM источник [. ... ] ]
[ [ NATURAL ] тип_обьединения источник
[ ON условие \ USING ( список_полей ) ] ]
[. ...]
[ WHERE условие ] [ GROUP BY критерий [. ...] ] [ HAVING условие [. ...] ]
[ { UNION | INTERSECT | EXCEPT } [ ALL ] подзапрос ] [ ORDER BY выражение
[ ASC | DESC | USING оператор ] [. ...] ]
[ FOR UPDATE [ OF таблица [. ...]]] [ LIMIT { число | ALL } [ { OFFSET | . } начало ] ]
В этом описании источник представляет собой имя таблицы или подзапрос. Эти общие формы имеют следующий синтаксис:
FROM { [ ONLY ] таблица [ [ AS ] синоним [ ( синоним_поля [....])]]] ( запрос )
[ AS ] синоним [ ( синоним_поля [. ...] ) ] }
- ALL. Необязательное ключевое слово ALL указывает на то, что в выборку включаются все найденные записи.
- DISTINCT [ ON ( выражение [, ...] ) ]. Секция DISTINCT определяет поле или выражение, значения которого должны входить в итоговый набор не более одного раза.
- цель [ AS имя ] [, ...]. В качестве цели обычно указывается имя поля, хотя цель также может быть константой, идентификатором, функцией или общим выражением. Перечисляемые цели разделяются запятыми, существует возможность динамического назначения имен целей в секции AS. Звездочка (*) является сокращенным обозначением всех несистемных полей, вместе с ней в списке могут присутствовать и другие цели.
- FROM источник [. ... ]. В секции FROM указывается источник, в котором PostgreSQL ищет заданные цели. В данном случае источник является именем таблицы или подзапроса. Допускается перечисление нескольких источников, разделенных запятыми (примерный аналог перекрестного запроса). Синтаксис секции FROM подробно описан ниже.
- [ NATURAL ] тип_объединения источник [ ON условие \ USING ( список_полей ) ]. Источники FROM могут группироваться в секции JOIN с указанием типа объединения (INNER, FULL, OUTER, CROSS). В зависимости от типа объединения также может потребоваться уточняющее условие или список полей.
- WHERE условие. Секция UHERE ограничивает итоговый набор заданными критериями. Условие должно возвращать простое логическое значение (true или false), но оно может состоять из нескольких внутренних условий, объединенных логическими операторами (например, AND или OR).
- GROUP BY критерий [, ... ]. Секция GROUP BY обеспечивает группировку записей по заданному критерию. Причем критерий может быть простым именем поля или произвольным выражением, примененным к значениям итогового набора.
- HAVING условие [. ... ]. Секция HAVING похожа на секцию WHERE, но условие проверяется на уровне целых групп, а не отдельных записей.
- { UNION | INTERSECT | EXCEPT } [ ALL ] подзапрос. Выполнение одной из трех операций, в которых участвуют два запроса (исходный и дополнительный);
- итоговые данные возвращаются в виде набора с обобщенной структурой, из которого удаляются дубликаты записей (если не было задано ключевое слово ALL):
- UNION — объединение (записи, присутствующие в любом из двух наборов);
- INTERSECT — пересечение (записи, присутствующие одновременно в двух наборах);
- EXCEPT — исключение (записи, присутствующие в основном наборе SELECT, но не входящие в подзапрос).
Выполнение запросов
Выполнение запросов
В psql существует два способа ввода и исполнения запросов (в psql этот термин означает команду SQL вообще). В интерактивном режиме запросы обычно вводятся непосредственно в приглашении командной строки (то есть из стандартного ввода). Команда psql \i читает файл локальной файловой системы и использует его содержимое в качестве входных данных.
Выражения константы и синонимы
Выражения, константы и синонимы
Целями команды SELECT могут быть не только простые поля, но и произвольные выражения (включающие вызовы функций или различные операции с идентификаторами) и константы. Синтаксис команды практически не изменяется, появляется лишь одно дополнительное требование — все самостоятельные выражения, , идентификаторы и константы должны разделяться запятыми. В списке разрешены произвольные комбинации разнотипных целей.
Команда SELECT также может использоваться для простого вычисления и вывода результатов выражений и констант. В этом случае она не содержит секции FROM или имен столбцов (листинг 4.25).
Запуск psql
Запуск psql
Перед запуском psql убедитесь в том, что двоичный файл psql находится в стандартном каталоге исполняемых файлов (например, /usr/bin), либо путь к каталогу двоичных файлов PostgreSQL (например, /usr/local/pgsql/bin) включен в список ката-
логов переменной среды PATH. За дополнительной информацией обращайтесь к главе 2.
Способ присваивания значения переменной PATH зависит от командного интерпретатора. В bash или ksh соответствующая команда может выглядеть так:
$ export PATH=$PATH:/usr/local/pgsql/bin
В интерпретаторах csh или tcsh используется несколько иной синтаксис:
$ set path=(Spath /usr/local/pgsql/bin)
Знакомство с psql
Знакомство с psql
Клиент psql работает в режиме командной строки и входит в комплект поставки PostgreSQL. Его часто называют интерактивным монитором или интерактивным терминалом. Этот простой, но мощный инструмент позволяет напрямую работать с сервером PostgreSQL и потому особенно хорошо подходит для экспериментов.
Операторы и функции
Агрегатные функции
Агрегатные функции
Агрегатными функциями называется особый класс функций, применяемых сразу к нескольким записям набора данных, но возвращающим одно значение. Обычно агрегатные функции используются в запросах с группировкой по критерию, заданному в секции GROUP BY, но также встречается их применение в запросах, у которых целевой список состоит только из агрегатных функций. В этом случае агрегатная функция обрабатывает все записи итогового набора.
В табл. 5.16 перечислены агрегатные функции, поддерживаемые в PostgreSQL. Полный список агрегатных функций выводится в psql командой \da.
Агрегатные выражения
Агрегатные выражения
При вызове агрегатной функции передается агрегатное выражение, применяемое к записям, созданным командой SELECT. По своей структуре агрегатные выражения сходны с обычными выражениями SQL, но они могут начинаться с ключевого слова ALL или DISTINCT.
Если задано ключевое слово DISTINCT, функция обрабатывает только группы с уникальными значениями агрегатного выражения; группы с повторяющимися значениями игнорируются. Ключевое слово ALL, как и в команде SELECT, всего лишь явно указывает на тот факт, что выражение относится ко всем группам. В листинге 5.19 приведены примеры разных форм агрегатных выражений.
Числовые операторы
Числовые операторы
Числовые операторы PostgreSQL делятся на три категории.
- Математические операторы выполняют математическую операцию с одним или двумя операндами и возвращают значение числового типа.
- Операторы сравнения проверяют заданное соотношение между двумя числовыми величинами (например, что одна величина больше другой) и возвращают результат проверки в виде типа boolean.
- Двоичные операторы работают на уровне отдельных битов, то есть единиц и нулей в двоичном представлении.
Двоичные операторы
Двоичные операторы
Двоичные операторы выполняют поразрядные операции с битовыми последовательностями или целыми числами, что обычно приводит к изменению их значений. Двоичные операторы PostgreSQL перечислены в табл. 5.6.
Функции для работы с датой и временем
Функции для работы с датой и временем
В PostgreSQL поддерживаются как стандартные функции SQL current_date, current_time и current_timestamp, так и множество нестандартных функций. Функции PostgreSQL, предназначенные для работы с датой и временем, перечислены в табл. 5.11.
Функции преобразования типа
Функции преобразования типа
Хотя PostgreSQL позволяет выполнять явные преобразования между основными типами данных, некоторые преобразования удобнее выполнять при помощи функций. В табл. 5.13 перечислены основные функции преобразования типов PostgreSQL, а ниже приводятся их подробные описания.
Функции
Функции
Функция представляет собой идентификатор, используемый в PostgreSQL для выполнения программных операций в командах SQL. Функции всегда возвращают одно значение, применяемое в команде SQL, из которой была вызвана функция. Происходящее отчасти напоминает возврат значения оператором, вызванным из запроса; более того, с технической точки зрения оператор представляет собой указатель на встроенную системную функцию. Таким образом, операторы можно рассматривать как удобную форму записи, упрощающую вызов системных функций.
Использование функций
Использование функций
При вызове функции в команде SQL указывается имя функции, после которого в круглых скобках перечисляются аргументы. Существует два основных стиля передачи аргументов. Стандартные функции SQL92 обычно реализуются так, что их аргументы разделяются специальными ключевыми словами SQL (такими, как FROM, FOR и USING). С другой стороны, функции в стиле PostgreSQL получают аргументы, разделенные запятыми (вероятно, программисту с опытом программирования на С этот способ покажется более привычным).
В качестве аргументов могут передаваться константы, допустимые идентификаторы или выражения. Интерпретация аргументов и их принадлежность к определенному типу данных полностью зависит от вызываемой функции. За именем функции практически всегда обязательно следуют круглые скобки, даже если при вызове не передаются аргументы.
функция_в_стиле_sq192 ( { аргумент \ КЛЮЧЕВОЕ_СЛОВО } [.:.] )
ipyHKuHz_Bj:THnej)gsql92 ( аргумент [, ...] )
ВНИМАНИЕ
Круглые скобки не обязательны только для функций SQL92 current_date, current_t1me и current_timestamp. В PostgreSQL эти функции также вызываются без круглых скобок, чтобы обеспечить совместимость со спецификацией SQL92.
Вызовы функции могут быть вложенными — при условии, что тип данных, возвращаемый внутренней функцией, совместим с типом соответствующего аргумента внешней функции. Допускается вложение вызовов на произвольную глубину:
имя_функции (имя_вложенной_функции (аргументы [. ... ] ) [. ...] )
В PostgreSQL существует множество стандартных функций, работающих со встроенными типами данных. Полный список функций выводится командой \df в клиенте psql. Кроме того, в PostgreSQL поддерживается возможность определения пользовательских функций при помощи команды CREATE FUNCTION. За дополнительной информацией обращайтесь к главе 7.
Примечание 1
Примечание 1
По умолчанию полям в целевом списке, значение которых определяется функцией, назначается синоним в виде имени функции без круглых скобок и без аргументов (например, to_char).
Конкатенация
Конкатенация
Оператор конкатенации (11) играет очень важную роль при форматировании выходных данных. Как и все операторы, он может использоваться в командах SQL всюду, где могут использоваться константы. Допускается последовательная конкатенация строковых значений, для этого перечисляемые строковые константы или идентификаторы разделяются операторами 11.
Например, оператор конкатенации может использоваться в секции WHERE для фильтрации записей на основании сравнения с символьной строкой. Пример приведен в листинге 5.4.
Правильное использование
Листинг 5.1. Правильное использование математического оператора
booktown=# SELECT id 1 AS id_p1us_one. 1ast_name
booktown-# FROM authors
booktown-# ORDER BY id DESC LIMIT 5;
id_plus_one j last_name
25042 Bianco 15991 | Bourgeois
7807 | Christiansen
7806 | Lutz
4157 I King
(5 rows)
Попытка сложения несовместимых типов продемонстрирована в листинге 5.2.
Использование операторов сравнения
Листинг 5.10. Использование операторов сравнения
booktown=# SELECT isbn, stock booktown-# FROM stock
booktown-# WHERE retail <= 25
booktown-# AND stock != 0:
isbn | stock
0441172717 | 77
0590445065 | 10
0679803335 | 18
0760720002 | 28
09296C5942 | 25
1885418035 | 77
(6 rows)
Ключевое слово BETWEEN
Листинг 5.11. Ключевое слово BETWEEN
booktown=# SELECT isbn FROM stock
booktown-# WHERE cost BETWEEN 10 AND 17;
isbn
0394800753 0441172717 0451457994
(3 rows)
Аналогичного результата можно добиться и при помощи оператора <= в сочетании с оператором >
= (листинг 5.12).
Имитация ключевого
Листинг 5.12. Имитация ключевого слова BETWEEN при помощи операторов
booktown=# SELECT isbn FROM stock
booktown-# WHERE cost >
= 10 AND cost <= 17; isbn
0394800753 0441172717 0451457994
(3 rows)
В варианте с ключевым словом BETWEEN команда выглядит более понятной. Впрочем, для PostgreSQL оба варианта эквивалентны, поэтому выбор зависит от личных предпочтений программиста.
Сдвиг битовых последовательностей
Листинг 5.13. Сдвиг битовых последовательностей
booktown=# SELECT b'1000' » 2 AS "8 shifted right".
booktown-# Mttoint4(b'1000' » 2) AS integer.
booktown-# 8 » 2 AS likewise;
8 shifted right | integer | likewise
0010 I 2 I 2
(1 row)
Примечание 2
Примечание 2
При сдвиге битовых последовательностей исходная длина строки не изменяется, а разряды, выходящие за левый или правый край последовательности, отсекаются. При использовании операторов &, | или # битовые операнды должны иметь одинаковую длину.
Объединение условий
Листинг 5.14. Объединение условий с использованием логических операторов
booktown=# SELECT isbn, cost, stock
booktown-# FROM stock
booktown-# WHERE cost >
30
booktown-# OR stock = 0:
Isbn cost | stock
0394900014 23.00 | 0
044100590X | 36.00 | 89
0451198492 | 36.00 | 0
0451457994 17.00 j 0 (4 rows)
booktown=# SELECT Isbn, cost, stock
booktown-# FROM stock
booktown-# WHERE cost >
30
booktown-# AND stock = 0;
Isbn | cost stock
0451198492 36.00 0
(1 row)
Проверка с использованием конструкции IS NULL
Листинг 5.15. Проверка с использованием конструкции IS NULL
booktown=# SELECT lastjiame, firstjiame
booktown-l FROM authors
booktown-* WHERE firstjiame IS NULL;
lastjiame fi rstjname
Geisel
(1 row)
При сравнении команд в листингах 5.15 и 5.16 может показаться, что эти два варианта синтаксиса идентичны. Тем не менее между ними существует принципиальное различие.
Сравнение со значением NULL
Листинг 5.16. Сравнение со значением NULL
booktown=# SELECT lastjiame, firstjiame
booktown-l FROM authors
booktown-f WHERE firstjiame = NULL:
lastjiame | fi rstjname
Geisel |
(1 row)
В PostgreSQL условие = NULL преобразуется в IS NULL, а условие != NULL преобразуется в IS NOT NULL. Это сделано только для совместимости с существующими клиентскими приложениями (например, Microsoft Access).
Тем не менее при сравнении значений с NULL вместо математических операторов = и != рекомендуется использовать конструкции IS NULL и NOT IS NULL. В настоящее время использование математических операторов = и != для сравнения со псевдозначениями NULL допускается ради совместимости с другими системами, но в будущем эта поддержка может быть ликвидирована, поскольку она не предусмотрена в стандарте SQL. По той же причине она не гарантирована в других СУБД на базе SQL.
Все остальные операторы сравнения для операнда NULL возвращают NULL, поскольку NULL никогда не бывает больше или меньше другой величины, отличной от NULL (листинг 5.17). NULL можно рассматривать как своего рода «черную дыру» в мире SQL — для этого псевдозначения ни один оператор сравнения (кроме IS NULL и специального оператора преобразования =) не возвращает true; NULL не может участвовать в операциях сложения, конкатенации и т. д.
Операторы и псевдозначение NULL
Листинг 5.17. Операторы и псевдозначение NULL
booktown=# \pset null *nu11* Null display is
booktown=# SELECT 5 >
NULL;
?column?
*null*
(1 row)
booktown=# SELECT NULL IS NULL;
? column?
t (1 row)
booktown=# SELECT NULL || 'Test'; ?column?
*null*
(1 row)
Приоритет операторов
Листинг 5.18. Приоритет операторов
booktown=# SELECT 60 + 12 * 5
AS "sixty plus twelve times five",
booktown-# 12 + 60 * 5
AS "twelve plus sixty times five";
sixty plus twelve times five |
twelve plus sixty times five
120 | 312
(1 row)
Как видно из листинга, результат выражения без круглых скобок, обеспечивающих нужный порядок выполнения операторов, в значительной степени зависит от порядка следования операндов. В приведенном примере первым всегда выполняется оператор умножения (несмотря на то, что оператор + расположен левее).
В табл. 5.8 перечислены группы операторов PostgreSQL в порядке убывания их приоритета.
Использование агрегатных выражений
Листинг 5.19. Использование агрегатных выражений
booktown=# SELECT count(location) AS setjocations,
booktown-# count(ALL location) AS all_set_locations,
booktown-# count(DISTINCT location) AS unique_locations,
booktown-# count(*) AS all_rows booktown-# FROM subjects;
setjocations | all_set_locations | uniquejocations all_rows
15 15 | 7 16
(1 row)
У агрегатных выражений также имеется специальная форма, продемонстрированная в столбце al l_rows выходных данных листинга 5.19. Если при вызове агрегатной функции передается звездочка (*), это означает, что функция должна обрабатывать все поля, в том числе и обычно игнорируемые поля со значениями NULL. Поскольку таблица subjects содержит одну запись с полем location, равным NULL, результат подсчета записей по полю 1 ocati on отличается от результата подсчета по тому же нолю с использованием символа *.
ВНИМАНИЕ
Записи, у которых в агрегатное выражение входит NULL, не обрабатываются агрегатными функциями (исключением является функция count().
avg()
Синтаксис: avg(выражение)
Функция avg() получает агрегатное выражение, результат которого относится к любому из числовых типов (numeric, bigint, smallint, real или double precision) или к типу interval.
Функция возвращает среднее арифметическое всех данных, описываемых выражением. Возвращаемое значение относится к типу numeric для выражения типа integer или к типу double precision для выражения типа real. В остальных случаях тип возвращаемого значения совпадает с типом выражения.
Неверное использование операторов
Листинг 5.2. Неверное использование операторов
booktown=# SELECT id + lastjiame AS mistake
booktown-# FROM authors:
ERROR: Unable to identify an operator '+' for types 'int4' and 'text' You will have to retype this query using an explicit cast
К счастью, в сообщениях о недопустимом использовании операторов в PostgreSQL указывается причина ошибки. Эта информация поможет вам устранить ошибку и внести необходимые исправления в команду.
Сравнение строк
Листинг 5.3. Сравнение строк
booktown=# SELECT title FROM books
booktown=# WHERE substrCtitle, 1, 1) < 'D1;
title
2001: A Space Odyssey
Bartholomew and the Oobleck
(2 rows)
Конкатенация строк
Листинг 5.4. Конкатенация строк
booktown=# SELECT 'The Title: ' | title || ', by ' |
booktown-# first_name || ' ' II lastjiame AS bookjinfo
booktown-# FROM books NATURAL JOIN authors AS a (authorjd) LIMIT 3;
book_info
The Title: The Shining, by Stephen King
The Title: Dune, by Frank Herbert
The Title: 2001: A Space Odyssey, by Arthur C. Clarke
(3 rows)
Поиск по регулярному выражению
Листинг 5.5. Поиск по регулярному выражению
booktown=# SELECT first_name, last_name
booktown-# FROM authors
booktown-# WHERE firstjiame - "AT1;
fi rstjiame lastjiame
Ariel Denham Tom Christiansen
Arthur C. | Clarke Andrew Brookins
Theodor Seuss j Geisel (5 rows)
Символ ~ в секции WHERE является оператором регулярного выражения, а само регулярное выражение задается строкой ЛА| ЛТ. В него входят специальные символы (метасимволы) л и |, а также литералы А и Т. Метасимволы регулярных выражений описаны ниже в этом пункте.
Важнейшее различие между функцией 11 ke() и операторами регулярных выражений заключается в том, что функция likeO ищет совпадение для всей строки, а операторы регулярных выражений ищут совпадение в произвольной позиции заданной строки, если только в самом регулярном выражении не указано обратное.
Операторы регулярных выражений перечислены в табл. 5.2. Их операндами всегда являются строка с регулярным выражением и текст, в котором ищется совпадение (идентификатор или константа). Все операторы регулярных выражении
возвращают результат логического типа, интерпретация которого зависит от специфики самого оператора.
Простой поиск соответствия
Листинг 5.6. Простой поиск соответствия
booktown=# SELECT title FROM books
booktown-# WHERE title - 'The';
title
The Shining The Cat in the Hat The Velveteen Rabbit
The Tell-Tale Heart
(4 rows)
booktown=# SELECT title FROM books
booktown-f WHERE title -* 'The'; title
The Shining The Cat in the Hat Bartholomew and
the Oobleck Franklin in the Dark The Velveteen Rabbit
The Tell-Tale Heart
(6 rows)
Как видно из результатов, оператор ~* возвращает две дополнительные записи, поскольку выражение соответствует не только подстроке «the», но и любым модификациям в регистре символов этой подстроки (the, tHe, ThE и т. д.).
Если добавить в начало этого регулярного выражения символ л, оно будет соответствовать только подстроке «The», находящейся в начале исходного текста (листинг 5.7).
Конструкция . * обозначает любое количество произвольных символов до следующего подвыражения. В данном примере этим подвыражением является пара строк в круглых скобках (rabbit и heart), разделенных символом |, что соответствует любой из перечисленных строк.
Нетривиальный поиск соответствия
Листинг 5.7. Нетривиальный поиск соответствия
booktown=f SELECT title FROM books
booktown-# WHERE title -* IAThe.*(rabbit|heart)';
title
The Velveteen Rabbit The Tell-Tale Heart
(2 rows)
Выражение AThe.*(rabbit|heart) означает следующее: соответствие находится лишь в том случае, если строка начинается с символов «The», далее идет любое количество произвольных символов, а после них следует либо подстрока «rabbit», либо подстрока «heart». Оператор ~* (вместо оператора ~) производит сравнение без учета регистра символов.
В листинге 5.8 приведен пример еще более сложного регулярного выражения.
Сложный поиск соответствия
Листинг 5.8. Сложный поиск соответствия
booktown=# SELECT title FROM books
booktown-# WHERE title ~* 'rt.*[ri]t) | (ingJjune$)' :
title
The Shining Dune
The Velveteen Rabbit The Tell-Tale Heart
(4 rows)
booktown=#
На первый взгляд регулярное выражение в листинге 5.8 выглядит устрашающе. Но если разбить его на элементы, становится видно, что оно состоит из двух выражений в круглых скобках, разделенных символом [.Таким образом, соответствие будет найдено, если хотя бы одно из этих выражений указывает на значение в поле title.
Продолжая анализ выражения, мы видим, что подвыражение слева от символа | состоит из следующих элементов (слева направо): метасимвол л, за которым следует символ t, затем последовательность .* и пара квадратных скобок с символами г и i, за которыми следует символ t. В переводе на русский язык это означает, что соответствие должно начинаться с буквы t, за которой следует ноль или более символов, пока не будет встречена буква г или 1, после которой немедленно следует буква t. Если хотя бы одно из этих условий не соблюдается, соответствия нет.
Выражение в правой части устроено проще. Оно состоит из двух литералов ing и une, разделенных очередным символом , причем за каждым литералом следует символ $. В переводе это означает, что совпадение должно заканчиваться подстрокой Ing или une. При выполнении любого (благодаря символу |) из этих условий соответствие считается найденным.
Использование математических операторов
Листинг 5.9. Использование математических операторов
booktown=# SELECT isbn,
booktown-# (retail / cost)::numeric(3, 2) - 1 AS margin
booktown-# FROM stock
booktowri-# ORDER BY margin DESC
booktown-# LIMIT 4;
isbn | margin
0451457994 | 0.35
0760720002 | 0.33
0451198492 0.30
0441172717 | 0.29
(4 rows)
Обратите внимание на определение временного псевдонима margin при помощи ключевого слова AS. Псевдоним представляет собой временное имя, которое существует только во время обработки запроса.
Логические операторы
Логические операторы
Ключевые слова AND, OR и NOT являются логическими (булевыми) операторами PostgreSQL. Обычно они используются для операций с логическими условиями в командах SQL, особенно в секциях WHERE и HAVING.
В табл. 5.7 приведена сводка результатов, возвращаемых логическими операторами AND, OR и NOT для всех возможных сочетаний операндов (true, false и NULL).
Математические функции
Математические функции
Математические функции PostgreSQL выполняют стандартные арифметические и тригонометрические операции и работают с разными типами данных. В большинстве случаев тип возвращаемого значения совпадает с типом аргументов функции. В табл. 5.9 приведена сводка основных математических функций PostgreSQL.
Математические операторы
Математические операторы
Математические операторы используются в целевых списках, в секции WHERE команды SELECT и вообще везде, где встречаются числовые данные.
В табл. 5.4 перечислены математические операторы PostgreSQL и приведены примеры их использования.
Операторы и функции
Операторы и функции
В этой главе рассматриваются операторы и функции PostgreSQL, то есть специальные символы и идентификаторы, предназначенные для модификации и сравнения данных в командах SQL. Результаты этих операций находят разнообразное применение, от обновления существующих записей в базе данных до ограничения результатов выборки по определенному критерию.
В PostgreSQL поддерживаются стандартные операторы и функции SQL, определенные в стандартах ANSI/ISO, — математические операторы, основные функции форматирования текста, выделение компонентов даты/времени и т. д. Кроме того, в PostgreSQL реализованы многочисленные нестандартные расширения, в том числе операторы поиска по регулярным выражениям и универсальная функция форматирования данных to_char().
Ниже описаны встроенные операторы и функции. Одной из замечательных особенностей языка PostgreSQL является возможность его расширения в этой области. Когда вы освоите стандартные операторы и функции, вероятно, вам захочется определить свои собственные. Эта тема рассматривается в главе 7.
Операторы и NULL
Операторы и NULL
Если таблица содержит значения NULL, можно воспользоваться специальными операторами сравнения, чтобы учесть поля NULL при выборке или игнорировать их. Конструкция IS NULL проверяет, содержит ли поле значение NULL. Обратное условие проверяется конструкцией NOT IS NULL.
В листинге 5.15 конструкция IS NULL используется для поиска авторов, у которых отсутствуют данные в поле f 1 rst_name.
Операторы регулярных выражений
Операторы регулярных выражений
Если обычного сравнения строк оказывается недостаточно, в PostgreSQL предусмотрены специальные операторы для поиска совпадений по регулярным выражениям. Регулярное выражение похоже на строковую константу, с которой сравнивается исходная строка, но некоторые символы (квадратные скобки, вертикальная черта, обратная косая черта и т. д.) при сравнении интерпретируются особым образом. Если вам доводилось работать с такими программами Unix, как sed, grep или perl, возможно, вы уже знакомы с синтаксисом регулярных выражений.
Примечание 2
Примечание 2
Общие сведения о регулярных выражениях приведены в книге Джеффри Фридла (Jeffrey Friedl) «Mastering Regular Expressions».
Регулярное выражение состоит из литералов и метасимволов (специальных символов). Обычно регулярные выражения могут совпадать с несколькими вариантами строковых значений. Пример приведен в листинге 5.5, где в таблице authors ищутся все имена (fi rstjiame), начинающиеся с символа А или Т.
Операторы сравнения
Операторы сравнения
Операторы сравнения работают со значениями таких типов, как integer или text, но всегда возвращают результат типа boo"! ean. Они часто встречаются в секции WHERE, но могут использоваться в любом контексте, в котором действителен тип boolean. Операторы сравнения PostgreSQL перечислены в табл. 5.5.
Операторы
Операторы
В главе 3 операторы SQL определялись как лексемы, предназначенные для выполнения операций с константами и идентификаторами и возвращающие результаты этих операций. Некоторые ключевые слова SQL тоже считаются операторами из-за воздействия на данные в командах SQL. В этом разделе термином «операторы» будут обозначаться как специальные символы, так и ключевые слова. Действия, выполняемые оператором, зависят от контекста его применения. Область применения операторов чрезвычайно широка, от выполнения математических операций и конкатенации строк до разнообразных сравнений. В следующем подразделе описываются общие правила применения операторов SQL, а далее подробно рассматриваются некоторые важнейшие категории операторов:
- строковые операторы;
- числовые операторы;
- логические операторы.
Примечание 1
Самый «свежий» и наиболее полный список операторов PostgreSQL выводится в psql командой \do. Помните, что многие из перечисленных операторов существуют только в PostgreSQL и могут не поддерживаться в других СУБД на базе SQL.
После описания различных категорий операторов приводится информация о роли псевдозначений NULL в выражениях и о порядке выполнения операторов.
Правила использования операторов
Правила использования операторов
Оператор работает с одним операндом или с двумя операндами. Большинство операторов работает с двумя операндами, между которыми ставится сам оператор (например, а-b). Такие операторы называются бинарными. Операторы, работающие с одним операндом, называются унарными; в этом случае оператор либо предшествует операнду, либо следует за ним (например, знак @ перед значением является унарным оператором, возвращающим модуль числа).
Некоторые операторы имеют несколько интерпретаций в зависимости от типа данных, к которым они применяются. С другой стороны, часть операторов не имеет смысла для некоторых типов данных (дополнительная информация о типах данных PostgreSQL приведена в главе 3).
Например, оператор сложения (+) может использоваться для суммирования двух целочисленных величии, но он не может прибавить целое число к текстовой строке. Считается, что такой вариант использования оператора дает неопределенный результат и потому является недопустимым. При этом сам оператор (в данном случае +) опознается нормально, но PostgreSQL выводит сообщение об ошибке (вроде того, что приведено в листинге 5.2).
Для примера рассмотрим таблицу authors, связывающую имена авторов с числовыми кодами.
Таблица "authors"
Атрибут | Тип | Модификатор
id | integer not null
lastjiame j text firstjname 1 text
Индекс: authors_pkey
Код автора id относится к типу integer (4-байтовое целое), а фамилия автора — к типу text. Поскольку поле id относится к числовому типу, оно может использоваться в качестве операнда математического оператора с другим числовым значением.
В листинге 5.1 приведен пример правильного использования оператора сложения (+).
возвращает арккосинус аргумента х, относящегося
testdb=# SELECT abs(lOO) AS abs_positive.
testdb-# abs(-lOO) AS absjiegative:
abs_positive | absjiegative
100 100
(1 row)
acos()
Синтаксис:
acos(x)
Функция acos () возвращает арккосинус аргумента х, относящегося к типу doubl e precision и лежащему в интервале допустимых значений косинуса (от -1 до 1). Фактически является обратной по отношению к функции cos(). Результат представляет собой угол (в радианах) в интервале от 0 до я, выраженный типом double precision.
и возвращает его экспоненту, то
testdb=# SELECT degrees(acos(-D) AS half_circle.
testdb-# degrees(pi) * 2) AS ful1_circle:
half_circle | full_circle
180 | 360
(1 row)
exp()
Синтаксис:
exp(x)
Функция получает один аргумент х типа numeri с или doubl e preci si on и возвращает его экспоненту, то есть результат возведения константы е в заданную степень.
получает один или два аргумента
booktown=# SELECT rpad('whitespace example'. 30): rpad
whitespace example (1 row)
booktown=# SELECT title. rpacKtitle. 12, ' -') AS right_dashed.
booktown-# rpad(title, 12, '-+-') AS right_plus_dashed
booktown-# FROM books
booktown-f LIMIT 3:
title [ right_dashed | right_plus_dashed
The Shining The Shining- | The Shining-Dune Dune
2001: A Space Odyssey 2001: A Spac 2001: A Spac
(3 rows)
rtrim()
Синтаксис:
rtrim(s)
trlm(s. f)
Функция rtri m() получает один или два аргумента типа text (аргумент f не обязателен). Если аргумент f не задан, функция возвращает строку s, из которой удалены все завершаю nine пробелы. В противном случае удаляется завершающая подстрока, состоящая только из символов, содержащихся в f. Если такая подстрока не найдена, s остается без изменений.
и округляет его до максимального
testdb=# SELECT exp(O.O) AS one.
testdb-# exp(l.O) AS e.
testdb-* exp(2.0) AS "e squared":
one I e I e squared
1 | 2.71828182845905 | 7.38905609893065
(1 row)
floor()
Синтаксис:
floor(x)
Функция f 1 оог() получает один аргумент х типа numeri с и округляет его до максимального целого, не большего переданной величины. Целые числа остаются без изменений.
Функция substrO эквивалентна функции SQL92
booktown=# SELECT title, strposdower(title), 'rabbit')
booktown-l FROM books
booktown-# WHERE strposdower(title), 'rabbit') != 0;
title | strpos
The Velveteen Rabbit | 15
(1 row)
substr()
Синтаксис:
substr(s. n) substr(s. n. 1)
Функция substrO эквивалентна функции SQL92 substring!), но аргументы передаются ей в стиле С. Функция вызывается с двумя или тремя аргументами s, n и 1 (необязательный аргумент), относящимися к типам text, т nteger и i nteger соответственно. Возвращаемое значение представляет собой подстроку s, начинающуюся с позиции п. Необязательный аргумент 1 определяет максимальную длину подстроки в символах.
Если заданная длина подстроки превышает количество оставшихся символов в строке s, возвращается только остаток строки. Иначе говоря, возвращаемое значение не дополняется до заданной длины.
one one point one one
testdb=# SELECT floor(l.O) AS one.
testdb-# floor(1.1) AS "one point one",
testdb-# floord.8) AS "one point eight";
one one point one one point eight
1 | 1 | 1
(1 row)
ln()
Синтаксис:
ln(x)
Функция ln(x) получает один аргумент х типа numeric или double precision и возвращает его натуральный логарифм. Фактически является обратной по отношению к функции ехр(). Эквивалентна вызову функции log() с передачей основания е.
с двумя или тремя аргументами
booktown=# SELECT title, substr(title, 15). substr(title. 5. 9)
booktown-# FROM books
booktown-# ORDER BY title DESC
booktown-# LIMIT 3;
title | substr | substr
The Velveteen Rabbit Rabbit | Velveteen
The Tell-Tale Heart Heart Tell-Tale
The Shining | | Shining
(3 rows)
substring()
Синтаксис:
substrts. n) substr(s, n. 1)
Функция SQL92 substring() эквивалентна функции PostgreSQLsubstr(). Функция вызывается с двумя или тремя аргументами s, n и 1 (необязательный аргумент), относящимися к типам text, integer и integer соответственно. Возвращаемое значение представляет собой подстроку s, начинающуюся с позиции п. Необязательный аргумент 1 определяет максимальную длину подстроки в символах.
получает один или два аргумента
testdb=# SELECT In(lO.O) AS naturaljog.
testdb-| log(expd.O). 10.0) AS naturaljog,
testdb-# In(expdO.O)) AS inverse_example:
naturaljog | naturaljog | inverse_example
2.30258509299405 | 2.30258509299404 | 10
(1 row)
log()
Синтаксис:
log(x) log(b.x)
Функция log() получает один или два аргумента типа numeric. Если передан один аргумент, возвращается его десятичный логарифм. Если переданы два аргумента, функция log(b.x) возвращает логарифм х по основанию Ь.
в строку f, заменяются символами
booktown=# SELECT to_ascii('Multibyte Source', 'LATIN1');
to_ascii
Multibyte Source
(1 row)
translate()
Синтаксис: translate(s. f. r)
Функция transl ate() получает три аргумента s, f и г, относящихся к типу text. В строке s все символы, входящие в строку f, заменяются символами с тем же индексом из строки г. Возвращаемое значение относится к типу text.
Обратите внимание: функция заменяет не экземпляры всей строки f, а любые символы, входящие в эту строку. Если f содержит больше символов, чем г, то все символы f, не имеющие аналогов в г, просто удаляются из s (удобный способ удаления ненужных символов).
В следующем примере все вопросительные знаки заменяются восклицательными.
logJ2 logJ2 log 12. base
testdb=# SELECT log(12.0) AS logj.2.
testdb-# logdO. 12.0) AS logj.2.
testdb-# log(3, 12.0) AS "log 12. base 3";
logJ2 logJ2 log 12. base 3
1.07918124604762 | 1.0791812460 | 2.2618595071
(1 row)
mod()
Синтаксис:
mod(x.y)
Функция mocK) получает два аргумента х и у, относящихся к числовым типам numeric, Integer, smallint или bigint. Возвращаемое значение представляет собой остаток от деления х на у.
В следующем примере все вхождения
booktown=# SELECT translated am an example?', '?', '!'):
translate
I am an example!
(1 row)
В следующем примере все вхождения символа «i» заменяются символом «w», а все вхождения символа «s» — символом «а». Лишний символ в конце строки «was» игнорируется.
и возвращает константу п, примерно
testdb=# SELECT mod(5. 5) AS no_remainder.
testdo-# mod(6, 5) AS remainder_one,
mod(19. 5) AS remainder_four;
no_remainder | rema1nder_one | remainder_four
0 | 1 | 4
(1 row)
pi()
Синтаксис:
pi()
Функция pi () вызывается без аргументов и возвращает константу п, примерно равную 3,14159265358978.
В последнем примере все гласные
booktown=# SELECT translate('This is a mistake.', 'is', 'was');
translate
Thwa wa a mwatake.
(1 row)
В последнем примере все гласные буквы заменяются пустой строкой, то есть удаляются из входной строки.
i on. Возвращаемое значение представляет
testdb=# SELECT pi() AS "the pi constant":
the pi constant
3.14159265358979
(1 row)
pow()
Синтаксис:
pow(x.y)
Функция pow() получает два аргумента х и у, относящихся к числовым типам numeri с или doubl e preci s i on. Возвращаемое значение представляет собой результат возведения х в степень у. Тип данных результата совпадает с типом переданных аргументов. Следует помнить, что аргументы должны содержать десятичную точку.
The Cat In the Hat
booktown=# SELECT title.
booktown-# translateCtitle, 'aeiouAEIOU', '') AS vowelless
booktown-# FROM books
booktown-f LIMIT 5;
title | vowelless
The Shining Th Shnng
Dune I Dn
2001: A Space Odyssey | 2001: Spc dyssy
The Cat In the Hat | Th Ct n th Ht
Bartholomew and the Oobleck Brthlmw nd th blck
(5 rows)
trim()
Синтаксис:
trim(направление f FROM s)
Функция SQL92 trim() способна заменить функции PostgreSQL rtrim(), ltrim() и btrim(). При вызове она получает три аргумента: ключевое слово (LEADING, TRAILING или BOTH) и две строки, f и s.
С ключевым словом LEADING функция trim() работает аналогично функции ItrimO, удаляя в начале строки s наибольшую подстроку, все символы которой входят в f.
С ключевым словом TRAILING функция trim() работает аналогично функции rtrim(), удаляя в конце строки s наибольшую подстроку, все символы которой входят в f.
С ключевым словом BOTH функция trim() работает аналогично функции btrim(), удаляя в начале и в конце строки s наибольшие подстроки, все символы которых входят в f.
d типа double precision, представляющий
testdb=# SELECT pow(2.0, 3.0) AS "two cubed".
testdb-# pow(2.0, 2.0) AS "two squared".
testdb-# pow(2.0, 1.0) AS "just two";
two cubed | two squared just two
8 | 4 2
(1 row)
radlans()
Синтаксис:
radians(d)
Функция radians () получает аргумент d типа double precision, представляющий угол в градусах, и преобразует его в радианы. Возвращаемое значение относится к типу double precision. Фактически функция radiansO является обратной по отношению к функции degrees ().
ORDER BY id ASC
booktown=# SELECT title, upper(title)
booktown-# FROM books
booktown-# ORDER BY id ASC
booktown-# LIMIT 3;
title | upper
The Tell-Tale Heart | THE TELL-TALE HEART
Little Women j LITTLE WOMEN
The Velveteen Rabbit | THE VELVETEEN RABBIT
(3 rows)
и возвращает псевдослучайное число типа
testdb=# SELECT radians(180) AS ha1f_circle.
testdb-# radians(360) AS fu11_circle;
half_circle | full_cnrcle
3.14159265358979 | 6.28318530717959
(1 row)
random ()
Синтаксис:
randon ()
Функция random() вызывается без аргументов и возвращает псевдослучайное число типа double precision в интервале от 0,0 до 1,0. При каждом вызове randonK) генерируется новое значение, даже если функция вызывается несколько раз в одном запросе.
Обычно функция random() используется в сочетании с математическими операторами (например, + и *) для получения псевдослучайных чисел в заданном интервале и последующим вызовом одной из функций округления (roundC), trunc() и т. д.).
SELECT randonK) AS natural random,
testdb=# SELECT randonK) AS natural random,
testdb-# round(randomO * 9) + I AS one_through_ten.
testdb-# truncC randonK) * 99) + 1 AS one_through_one_hundred:
natural_random | one_through_ten | one_through_one_hundred
0.478887704424042 | 2 | 37
(1 row)
round ()
Синтаксис:
round(x) round(x.s)
Функция roundO вызывается с одним или с двумя аргументами. Первый аргумент х относится к типу numeric или double precision и определяет округляемое число. Второй необязательный аргумент s относится к типу integer и определяет количество цифр в дробной части после округления. Тип возвращаемого значения совпадает с типом первого аргумента.
Если значение аргумента s больше количества цифр в дробной части х, недостающие позиции заполняются нулями.
Функция получает один или два
booktown=# SELECT asciitТ); ascii
84
(1 row)
booktown=# SELECT DISTINCT ON (substr)
booktown-# title. substrCtitle, 1, 1),
booktown-# ascii(tltle)
booktown-# FROM books
booktOMl-f ORDER BY substr ASC:
title | substr ascii
2001: A Space Odyssey | 2 | 50
Bartholomew and the Oobleck j В I 66
Dune |D 68
Franklin in the Dark | 70
Goodnignt Moon | G j 71
Little Women L 76
Practical PostgreSQL | P j 80
The Shining Т 84
(8 rows)
btrim()
Синтаксис:
btrim(s) btrim(s. t)
Функция получает один или два аргумента типа text, второй аргумент t не является обязательным. Если аргумент t задан, функция удаляет в начале и в конце строки s все символы, входящие в строку t. Если функция вызвана с одним аргументом, удаляются начальные и конечные пропуски — пробелы, символы табуляции и т. д.
Порядок перечисления символов в строке t для функции btrim() значения не имеет. В начале и конце строки s удаляются подстроки, полностью состоящие из символов, входящих в строку t.
Функция current_time вызывается без аргументов
booktown=# SELECT current_date,
booktown-# 'now'::date AS date;
date date
2001-08-31 | 2001-08-31
(1 row)
current_time
Синтаксис:
current_time
Функция current_time вызывается без аргументов и возвращает текущее время в виде значения типа time. Результат эквивалентен преобразованию специальной константы now к типу time.
фактически является обратной по отношению
booKtown=# SELECT bitfronrint4(16385);
bitfromint4
00000000000000000100000000000001
(1 row)
bittoint4()
Синтаксис:
bittoint4(b)
Функция bittoint4() фактически является обратной по отношению к bitfromint4() — она получает один аргумент b тина bit п возвращает его десятичное числовое значение в виде тина integer.
Соответственно аргумент функции bitfrwint4() содержит до 32 двоичных цифр, а возвращаемое значение лежит в интервале от -2 147 483 648 до 2 147 483 647.
возвращает арксинус аргумента х, относящегося
testdb=# SELECT acos(l). acos(O),
acos(-l). testdb-# acos(cosd)) AS inverse_example:
acos | acos | acos | inverse_example
0 | 1.5707963267949 | 3.14159265358979 |
(1 row)
asin()
Синтаксис:
asln(x)
Функция as1n() возвращает арксинус аргумента х, относящегося к типу double jrecisi on и лежащему в интервале допустимых значений синуса (от -1 до 1). Факти-lecKii является обратной по отношению к функции sin(). Результат представляет со-юй угол (в радианах) в интервале от -я/2 до л/2, выраженный типом doubl e preci s I on.
e preci si on, представляющий
testdb=# SELECT round(l.O) AS one,
testdb-# round(l.l) AS "one point one",
testdb | round(1.5) AS "one point five",
testdb-# roundd.8) AS "one point eight";
one | one point one |
one point five | one point eight
1 | 1 | 2 | 2
(1 row)
testdb=# SELECT round(1.4949. 1) AS one_digit_scale.
testdb-# roundd.4949, 3) AS three_digit_scale.
testdb-# roundd.4949, 10) AS ten_digit_scale.
testdb-# roundd.4949. 0) AS rounded;
one_digit_scale | three_digit_scale | ten_digit_scale rounded
1.5 1.495 | 1.4949000000 1
(1 row)
Sin()
Синтаксис:
Sin(x)
Функция si n () получает один аргумент х типа doubl e preci si on, представляющий угол в радианах, и возвращает синус этого угла в виде значения типа doubl e preci si on.
х типа double precision или
testdb=# SELECT sin(pi() / 4) AS quarter_pi,
testdb-# sin(pi() / 2) AS half_pi:
quarter_pi | half_pi
0.707106781186547 |
(1 row)
sqrt()
Синтаксис:
sqrt()
Функция sqrt() получает один числовой аргумент х типа double precision или lumeric и возвращает квадратный корень, при этом тип возвращаемого значения ювпадает с типом аргумента. Фактически является обратной по отношению к Ьункции pow(), выполняющей возведение во вторую степень.
e preci si on, представляющий
estdb=# SELECT sqrt(2.0), sqrt(4.0),
estdb-# sqrt(pow(2.0, 2)) AS inverse_example:
sqrt | sqrt | inverse_exampl
1.4142135623731 2 | 2
(1 row)
tan()
Синтаксис:
tan(x)
Функция tan() получает один аргумент х типа doubl e preci si on, представляющий тол в радианах, и возвращает тангенс этого угла в виде значения типа doubl e preci s i on.
с двумя аргументами. Первый аргумент
testdb=# SELECT tan(pi() / 8).
testdb-# tan(O): tan | tan
0.414213562373095 |
(1 row)
trunc()
Синтаксис:
trunc(x) trunc(x.s)
Функция trunc() вызывается с одним или с двумя аргументами. Первый аргумент х относится к типу numeric или double precision и определяет исходное число. Второй необязательный аргумент s относится к типу integer и определяет количество цифр в дробной части после усечения.
Если аргумент s не задан, отсекаются все цифры в дробной части числа. Если значение аргумента s больше количества цифр в дробной части х, недостающие позиции заполняются нулями.
AS one_decima1_point,
testdb=# SELECT trunc(1.598) AS natural-truncation.
testdb-# trunc(1.598. 1) AS one_decima1_point,
testdb-# trunc(1.598, 8) AS extra_places:
natural_truncation one_decimal_point | extra_places
1 | 1.5 | 1.59800000
(1 row)
Функция SQL92 char_l engthC) получает
booktown=# SELECT btrimC whitespace example ') AS trim_blanks,
booktown-# btr1m('123example 332', '123') AS trimjnumbers:
trim_blanks | trim_numbers
whitespace example example
(1 row)
char_length()
Синтаксис:
charjength(s)
Функция SQL92 char_l engthC) получает один аргумент s типа text, varchar или character и возвращает длину полученной строки в символах. Возвращаемое значение относится к типу integer.
Функция current_timestamp вызывается без аргументов
booktown=# SELECT current_time,
booktown-# 'now'::time AS time;
time | time
11:36:52 | 11:36:52
(1 row)
current_timestamp
Синтаксис:
current_timestamp
Функция current_timestamp вызывается без аргументов и возвращает текущее время в виде значения типа timestamp. Результат эквивалентен преобразованию специальной константы now к типу timestamp или вызову функции now().
f типа text, форматирует число
booktown=# SELECT bittoint4(B'101010').
booktown-# Mttoint4(bitfromint4(99))
AS inverse_example: bittoint4 inverse_example
42 | 99
(1 row)
to_char() для чисел
Синтаксис:
to_char(n. f)
Функция to_char(), вызываемая с аргументом п типа numeri с и аргументом f типа text, форматирует число п в строку типа text. Строка f описывает формат выходного значения.
Форматная строка f состоит из метасимволов, вместо которых PostgreSQL подставляет представляемые ими значения. Метасимволы, используемые в форматных строках, перечислены в табл. 5.14.
О возвращает арктангенс аргумента х,
testdb=# SELECT asin(l), asin(O), asin(-l),
testdb-# asin(sind)) AS inverse_examp1e;
asin | asin [ asin [ lnverse_example
1.5707963267949 0 | -1.5707963267949 | 1
(1 row)
itan()
Синтаксис:
itan(x)
Функция atari О возвращает арктангенс аргумента х, относящегося к типу doubl e )reci slon. Фактически является обратной по отношению к функции tan(). Результат представляет собой угол (в радианах) в интервале от -л/2 де я/2, выраженный типом double precision.
равным п. Возвращаемое значение относится
booktown=# SELECT charjength(title). title
booktown-l FROM books Dooktown-# LIMIT 3: charjength | title
11 | The Shining
4 Dune
21 I 2001: A Space Odyssey
(3 rows)
chr()
Синтаксис: chr(n)
Функция chr() получает один числовой аргумент п типа integer и возвращает символ с ASCII-кодом, равным п. Возвращаемое значение относится к типу text. Функция chr() фактически является обратной по отношению к функции asci 1 ().
получает два аргумента. Первый аргумент
booktown=# SELECT current_timestamp.
booktown-# now() AS timestamp;
timestamp | timestamp
2001-08-31 11:39:42-07 2001-08-31 11:39:42-07
(1 row)
date_part()
Синтаксис:
date_part(s. t) date_part(s. i)
Функция date_part() получает два аргумента. Первый аргумент s относится к типу text, а второй, t или I, — к типу timestamp или interval соответственно. Функция выделяет во втором аргументе компонент, определяемый строкой s, и возвращает его в виде значения типа doubl e preci si on.
Чтобы лучше понять, как работает функция date_part(), представьте, что значение типа timestamp или interval делится на компоненты — часы, минуты и т. д. Эти компоненты (и соответственно допустимые значения аргумента s) перечислены в табл. 5.12. Помните, что некоторые значения относятся только к типу tlmestamp и не поддерживаются для типа Interval.
Модификатор FM имеет важное значение
booktown=# SELECT timestamp('197825thJuly01:12am')
booktown-# AS non_standard_timestamp,
booktown-l to_fimestamp('197825July01:12am',
booktown(# 'YYYYDDFMMonthHH12:MIam')
booktown-# AS correcMnterpretation;
non_standard_timestamp | correctjnterpretation
2025-06-27 01:12:00-07 1978-07-25 01:12:00-07
(1 row)
Примечание 3
Примечание 3
Модификатор FM имеет важное значение для правильной интерпретации данных, следующих за названием месяца или дня недели, поскольку эти названия часто дополняются пробелами до 9 символов. Помните, что модификатор FM не является глобальным — он должен предшествовать каждом/элементу, к которому он применяется.
timestamp()
Синтаксис:
timestamp(d) timestamptd, t)
Функция ti mestampC) получает либо один аргумент типа date, либо два аргумента типов date и time соответственно. Переданные аргументы преобразуются в значение типа tlmestamp и возвращаются функцией. При передаче одного аргумента предполагается, что время соответствует полуночи заданной даты.
возвращает арктангенс, то есть угол
testdb=# SELECT atan(l). atan(O). atan(-l),
testdb-# atan(tand)) AS inverse_example;
atan atan | atan | inverse_example
0.785398163397448 | 0 | -0.785398163397448 | 1
(1 row)
itan2()
Синтаксис:
3tari2(x.y)
По аналогии с функцией atan(), функция atan2() возвращает арктангенс, то есть угол (в радианах) в интервале от -я/2 до я/2, выраженный типом doubl e preci si on. Однако в отличие от atan() она получает два аргумента типа double precision вместо одного и возвращает арктангенс величины, полученной делением первого аргумента на второй.
В общем случае вызов функции atan2(x,y) эквивалентен вызову atan(x/y), но при передаче аргумента у=0 функции atan2() не происходит ошибки деления на ноль, как при вызове atan() для величины х/у. Если аргумент у равен нулю, функция atan2() возвращает я/2 для положительных значений х, -я/2 для отрицательных х и 0 для х=0.
s типа text, varchar или
booktown=# SELECT initcapCa prospective book title'):
initcap
A Prospective Book Title
(1 row)
length()
Синтаксис:
length(s)
Аналог функции SQL92 charj ength(). Получает один аргумент s типа text, varchar или character и возвращает длину полученной строки в символах в виде значения типа integer.
Функция SQL92 extractO представляет собой
booktown=# SELECT date_trune('minute', now());
date trunc
2001-08-31 09:59:00-07
(1 row)
booktown=# SELECT date_trunc( 'hour', now());
date trunc
2001-08-31 09:00:00-07 (1 row)
booktown=# SELECT date_trunc('year', now());
date trunc
2001-01-01 00:00:00-08
(1 row)
extract()
Синтаксис:
extract(k FROM t) extract(k FROM 1)
Функция SQL92 extractO представляет собой аналог функции PostgreSQL date_part() со слегка измененным синтаксисом. При перечислении аргументов вместо запятой используется ключевое слово FROM. Аргументы аналогичны аргументам функции date_part(), хотя первый аргумент является ключевым словом SQL, а не строкой и поэтому не заключается в кавычки. Допустимые значения k перечислены в табл. 5.12.
Учтите, что функция extractO является «псевдонимом» функции PostgreSQL date_part () в синтаксисе SQL92, поэтому по умолчанию в выходных данных функция extract() представляется именем date_part.
AS today_at_midnight,
booktown=# SELECT timestamp(date('now'))
AS today_at_midnight,
booktown-# timestamp(dateCnow'),
booktownd time('now')) AS right_now;
today_at_m1dnight | rightjiow
2001-09-01 00:00:00-07 | 2001-09-01 18:04:16-07
(1 row)
и возвращает кубический корень, также
testdb=# SELECT atan2(0, 1). atan2(l, 1),
testdb-# atanCO / 1) AS functionally.
testdb-# atand / 1) AS identical;
atan2 atan2 | functionally identical
0 i 0.785398163397448 | 0 | 0.785398163397448 (1 row)
testdb=# SELECT atan2(l, 0) AS positive_x.
testdb-# atan2(-l, 0) AS negative_x,
testdb-# atan2(0, 0) AS zero_x,
testdb-i pi() / 2 AS pi_over_two:
positive_x | negative_x | zero_x \ pi_over_two
1.5707963267949 | -1.5707963267949 | 0 | 1.5707963267949
(1 row)
cbrt()
Синтаксис:
cbrt()
Функция cbrt () получает один числовой аргумент х типа doubl e preci si on и возвращает кубический корень, также представленный типом double precision. Фактически является обратной по отношению к функции pow(), выполняющей возведение в третью степень.
В стандарт SQL92 включены две
booktown=# SELECT length(title), title
booktown-# FROM books
booktown-# LIMIT 3; length title
11 | The Shining 4 I Dune
21 | 2001: A Space Odyssey
(3 rows)
Примечание 1
Примечание 1
В стандарт SQL92 включены две функции определения длины строки: char_length() и octet_length(). Следовательно, эти две функции с большей, чем функция length(), вероятностью будут поддерживаться другими реляционными СУБД.
like() и ilike()
Синтаксис:
s like (f) s LIKE f like(s.f) s ilike(f) s HIKE f
Функция 1 i ke() проверяет, совпадает ли выражение, заданное аргументом f, со строкой s. При вызове функции либо передаются два аргумента типа text, либо используется специальный синтаксис SQL, в котором аргумент s предшествует имени функции. Функция 11 i ke() является нестандартной версией функции 11 ke(), игнорирующей регистр символов при сравнении, и вызывается только в синтаксисе SQL.
Примечание 2
Примечание 2
Ключевое слово SQL LIKE в PostgreSQL заменяется вызовом функции likeO. Возможность использования ключевого слова LIKE без круглых скобок — всего лишь синтаксическое удобство, на практике оба варианта эквивалентны.
Использование функции 1 ike() отличается от обычного сравнения с помощью оператора =, поскольку строка f может содержать символы подчеркивания (_) или процента (%), интерпретируемые особым образом. PostgreSQL интерпретирует символ _ как один произвольный символ, а символ % — как ноль или более произвольных символов. Эти специальные символы могут находиться в любом месте строки f.
В PostgreSQL существуют и более совершенные средства поиска по шаблону, о которых говорилось в пункте «Операторы регулярных выражений» подраздела «Строковые операторы» раздела «Операторы» этой главы.
в виде значения типа timestamp.
booktown=# SELECT isfinite('now'::timestamp) AS now_is_finite,
booktown-# isfinite('infinity'::timestamp) AS Infinity,
booktown-# isfiniteC'invalid'::timestamp) AS invalid;
now_is_finite | infinity | invalid
(1 row)
now()
Синтаксис:
now()
Функция now() вызывается без аргументов и возвращает текущую дату и время в виде значения типа timestamp.
получает один числовой аргумент х,
testdb=# SELECT pow(2.0. 3) AS "two cubed".
testdb-# cbrt(8.0) AS "eight's cube root";
two cubed | eight's cube root
8 | 2
(1 row)
ceil()
Синтаксис:
ceil(x)
Функция cei 1 () получает один числовой аргумент х, относящийся к любому из числовых типов данных (numeric, bigint, smallint, real или double precision), и округляет его до минимального целого, не меньшего переданной величины. Целые числа остаются без изменений.
с двумя или тремя аргументами
booktown=# SELECT lower(title)
booktown-# FROM books
booktown-# LIMIT 3;
lower
tne shining
dune
2001: a space odyssey
lpad()
Синтаксис:
lpad(s. n) 1pacl(s. n. c)
Функция lpad() вызывается с двумя или тремя аргументами s, n и с (необязательный аргумент), относящимися к типам text, Integer и text соответственно. Строка s дополняется слева до длины n символов пробелами или содержимым необязательного аргумента с.
Если начальная длина строки s больше п, строка усекается справа до длины п.
и дату. Она похожа на
booktown=# SELECT now();
now
2001-08-31 10:31:18-07
(1 row)
timeofday()
Синтаксис: timeofdayO
Функция timeofday() вызывается без аргументов и возвращает текущие время и дату. Она похожа на функцию now(), но возвращает значение типа text. Это делает ее менее удобной, поскольку значение не разделяется на компоненты функциями date_part() и to_char() без предварительного преобразования к другому типу.
х типа double precision, представляющий
testdb=# SELECT ceil(1.0). ceil(1.1), ceil(1.5);
ceil | ceil ceil
1 | 2 | 2
(1 row)
COS()
Синтаксис:
COSU)
Функция cos О получает один аргумент х типа double precision, представляющий угол в радианах, и возвращает косинус этого угла в виде типа doubl e preci si on.
SELECT title. IpadCtitle, 12, AS
booktown=# SELECT title. IpadCtitle, 12, AS dashed,
booktown-# IpadCtitle. 12. '-+-') AS pius_dashed
booktown-# FROM books LIMIT 4;
title | dashed | plus_dashed _
The Shining | -The Shining | -The Shining
Dune |Dune Dune
2001: A Space Odyssey | 2001: A Spac | 2001: A Spac
The Cat in the Hat | The Cat in t | The Cat in t
(4 rows)
Itrim()
Синтаксис:
Itrim(s) ItrimCs. f)
Функция 11 ri m() получает один или два аргумента типа text (аргумент f не обязателен). Если аргумент f не задан, функция возвращает строку s, из которой удалены все начальные пробелы. В противном случае удаляется начальная подстрока, состоящая только из символов, содержащихся в f. Если такая подстрока не найдена, s остается без изменений.
Fn Aug 31
Dooktown=# SELECT timeofday();
timeofday
Fn Aug 31 10:33:00.837338 2001 PDT
(1 row)
х типа double precision, представляющий
testdb=# SELECT cos (pi О) AS cosj>i.
testdb-# cos(O) AS cos_zero:
cos_pi | cos_zero
1 | 1
(1 row)
cot()
Синтаксис:
cot(x)
Функция cot() получает один аргумент х типа double precision, представляющий угол в радианах, и возвращает котангенс этого угла в виде типа doubl e preci s i on. Аргумент должен быть отличным от нуля.
The Cat in the Hat
booktown=# SELECT title, positiorK'the' IN title) AS the_pos
booktown-# FROM books
booktown-# WHERE positionCthe1 IN title) != 0:
title | the_pos
The Cat in the Hat | 12
Bartholomew and the Oobleck | 17
Franklin in the Dark 13
(3 rows)
repeat()
Синтаксис: repeat(s. n)
Функция repeat О получает два аргумента s и п, относящихся к типам text и integer соответственно. Функция возвращает символьную строку s, повторенную п раз, в виде значения типа text.
г типа double precision, представляющий
testdb=# SELECT cot(l). cot(-l):
cot cot
0.642092615934331 | -0.642092615934331
(1 row)
degrees()
Синтаксис:
degrees(r)
Функция degreesO получает аргумент г типа double precision, представляющий угол в радианах, и преобразует его в градусы. Возвращаемое значение относится к типу double precision. Фактически функция degreesO является обратной по отношению к функции radians().
Функция rpadO похожа на функцию
booktown=# SELECT repeat(lastjname. 2)
booktown-l FROM authors booktown-# LIMIT 3; repeat
DenhamDenham BourgeoisBourgeois BiancoBianco
(3 rows)
rpad()
Синтаксис:
rpad(s. n) rpad(s. n. c)
Функция rpadO похожа на функцию IpadO, но дополняет строку справа, а не слева. Она вызывается с двумя или тремя аргументами s, n и с (необязательный аргумент), относящимися к типам text, integer и text соответственно. Строка s дополняется справа до длины п символов пробелами или содержимым необязательного аргумента с.
Если начальная длина строки s больше п, строка усекается слева до длины п.
Функция initcapO получает один аргумент
booktowrHf SELECT chr(65), ascii('A');
chr ! ascii
A | 65
(1 row)
initcap()
Синтаксис: initcap(s)
Функция initcapO получает один аргумент s типа text, преобразует первые буквы всех слов к верхнему регистру и возвращает полученную строку. В данном контексте «словом» считается любая последовательность символов, отделенная от других слов пробелами.
получает два аргумента типа text.
booktown=# SELECT to_char(now(). 'HH:MI PM1) AS the_time;
the_time
05:04 PM
(1 row)
booktown=# SELECT to_char(now(), 'Dy (Day), Mon (Month)')
booktown-# AS abbreviations,
booktown-# to_char('yesterday'::timestamp, 'FMMonth FMDDth')
booktown-# AS yesterday.
booktown-# to_char('yesterday':itimestamp, 'FMDDth FMMonth')
booktown-# AS "yesterday UK";
abbreviations | yesterday j yesterday UK
Sat (Saturday ). Sep (September) | August 31st | 31st August
(1 row)
booktown=# SELECT isbn,
booktown-# to_char(publication, 'FMMonth FMDDth, YYYY')
booktown-# AS informal,
booktown-# to_char(publication, 'YYYY-MM-DD') AS formal,
booktown-# to_char(publication. 'Y.YYY "years" A.D.')
booktown-# AS firstj)ublished
booktown-# FROM editions LIMIT 3;
isbn | informal | formal first_pub1ished
039480001X | March 1st. 1957 1957-03-01 1.957 years A.O.
0451160916 | August 1st. 1981 | 1981-08-01 | 1.981 years A.D.
0394800753 | March 1st. 1949 | 1949-03-01 | 1.949 years A.D.
(3 rows)
to date()
Синтаксис:
to_date(s. f)
Функция to_date() получает два аргумента типа text. Аргумент f описывает формат даты, представленной строкой s, и содержит метасимволы из табл. 5.15. Результат возвращается в виде значения типа date.
В PostgreSQL поддерживается много распространенных форматов данных, однако предусмотреть все форматы невозможно. Функция to_date() гарантирует, что практически любой формат даты, описываемый метасимволами из табл. 5.14, может быть преобразован в значение типа date.
Пример
booktown=# SELECT date('198025thJune')
booktown-f AS non_standard_date_format,
booktown -# toJate (' 198025thJune', ' YYYYDDthMonth')
booktown-# AS correct_interpretation;
non_standard_date_format correct_interpretation
2025-08-27 | 1980-06-25
(1 row)
to_number()
Синтаксис:
to_number(s. f)
Функция to_number() получает два аргумента типа text. Аргумент f описывает формат числа, представленного строкой s, и содержит метасимволы из табл. 5.14. Результат возвращается в виде значения типа numeric.
получает два аргумента типа text.
booktown=# SELECT to_number('$2,900.00', 'L9G999D99')
booktown-# AS monetary: monetary
2900.00 (1 row)
booktown=# SELECT tojiumber('123.456.789.00' . '999G999G999D99')
booktown-# AS formatted,
booktown-# to_numberС123456789'. '999999999')
booktown-# AS just_digits,
booktown-# to_number('00123456789'. '00999999999')
booktown-# AS leading_zeroes;
formatted | just_d1gits | leading_zeroes
123456789.00 123456789 | 123456789
(1 row)
to_timestamp()
Синтаксис:
to_timestamp(s. f)
Функция to_timestamp() получает два аргумента типа text. Аргумент f описывает формат даты/времени, представленного строкой s, и содержит метасимволы из табл. 5.15. Результат возвращается в виде значения типа date.
Эта функция, как и to_date(), прежде всего обеспечивает возможность правильной интерпретации нестандартных строк, содержащих дату и время.
FROM stock JOIN editions USING
booktown=# SELECT avg(cost) AS average_cost,
booktown-# avg(retail) AS average_price,
booktown-# avg(retail - cost) AS average_profit
booktown-# FROM stock:
average_cost | average_price | average_prof1t
24.8235294118 | 30.0088235294 5.1852941176
(1 row)
x>oktown=# SELECT avg(cost)
AS average_cost, p.name AS publisher
booktown-# FROM stock JOIN editions USING (isbn))
booktown-l JOIN publishers AS p (publisheMd)
booktown-# USING (publisheMd)
booktown-# GROUP BY p.name;
average_cost | publisher
26.5000000000 | Ace Books
19.0000000000 | Books of Wonder
26.5000000000 I Doubleday
25.0000000000 | HarperCollins
18.0000000000 | Henry Holt & Company. Inc.
23.0000000000 I Kids Can Press
23.0000000000 | Mojo Press
20.0000000000 I Penguin
23.0000000000 Random House
26.5000000000 | Roc
26.0000000000 | Watson-Guptill Publications
(11 rows)
count()
Синтаксис:
count(выражение)
Функция countO возвращает количество значений, для которых выражение отлично от NULL. Тип выражения не ограничивается. Следует помнить, что функция count () подсчитывает только значения, отличные от NULL, поэтому для получения осмысленных результатов используемое выражение не должно возвращать NULL для подсчитываемых записей.
Если при вызове count() передается символ *, функция просто подсчитывает все записи, в том числе и содержащие NULL.
FROM editions JOIN publishers AS
booktown=# SELECT countC*) FROM editions;
count
17
(1 row)
booktown=# SELECT count(isbn). p.name
booktown-# FROM editions JOIN publishers AS p (publisheMd)
booktown-# USING (publisheMd)
booktown-# GROUP BY p.name
booktown-# ORDER BY count DESC;
count | name
3 | Random House
2 | Ace Books
2 | Doubleday
2 Roc
1 | Books of Wonder
1 | HarperCollins
1 | Henry Holt & Company. Inc.
1 | Kids Can Press
1 | Mojo Press
1 | O'Reilly & Associates
1 | Penguin
1 | Watson-Gupti11 Publications
(12 rows)
max()
Синтаксис:
max(выражение)
Функция max() возвращает максимальное значение заданного выражения в группе. Результатом выражения может быть значение любого числового или строкового типа, а также типа даты или времени. Тип возвращаемого значения совпадает с типом выражения.
возвращает минимальное значение заданного выражения
booktown=# SELECT max(cost), max(retail) FROM stock;
max max
36.00 I 46.95
(1 row)
booktown=# SELECT max(retail), p.name
booktown-# FROM (stock NATURAL JOIN editions)
booktown-# JOIN publishers AS p (publisher_id)
booktown-# USING (publisherjd)
booktown-# GROUP BY p.name
booktown-# ORDER BY max DESC;
max | name
46.95 | Roc
45.95 i Ace Books 36.95 Doubleday 32.95
Random House 28.95 HarperCollins
28.95 I Watson-Guptill Publications
24.95 | Mojo Press
24.95 | Penguin
23.95 1 Henry Holt & Company. Inc. 23.95
Kids Can Press 21.95 Books of Wonder
(11 rows)
min()
Синтаксис:
min (выражение)
Функция min() возвращает минимальное значение заданного выражения в группе. Результатом выражения может быть значение любого числового или строкового типа, а также типа даты или времени. Тип возвращаемого значения совпадает с типом выражения.
О получает выражение, описывающее значения
booktown=# SELECT min(cost). min(retail) FROM stock;
min | min
16.00 16.95
(1 row)
booktown=# SELECT min(retail), p.name
booktown-# FROM (stock NATURAL JOIN editions)
booktown-# JOIN publishers AS p (publisheMd)
booktown-# USING (publisheMd)
booktown-l GROUP BY p.name
booktown-# ORDER BY min ASC;
miP 1 ..mme._
16.95 | Random House
21.95 Ace Books
21.95 I Books of Wonder
22.95 | Roc
23.95 | Henry Holt & Company. Inc.
23.95 | Kids Can Press
24.95 | Mojo Press
24.95 I Penguin
28.95 | Doubleday
28.95 I HarperCollins
28.95 | Watson-Guptill Publications
(11 rows)
stddev()
Синтаксис:
stddev(выражение)
Функция stddev О получает выражение, описывающее значения любого числового типа (numeri с, bigi nt, smal 1 i nt, real или doubl e preci si on), и возвращает среднеквадратичное отклонение для группы. Для вещественных выражений результат возвращается в виде значения типа double precision, а для остальных типов —в виде значения типа numeric.
получает выражение, описывающее значения любого
booktown=# SELECT stddev(retail) FROM stock;
stddev
8.46
(1 row)
booktown=# SELECT stddev(retail), p.name
booktown-# FROM (stock NATURAL JOIN editions)
booktown-# JOIN publishers AS p ON (publisheMd = p.id)
booktown-# GROUP BY p.name
booktown-# ORDER BY stddev DESC
booktown-# LIMIT 4:
stddev | name
16.97 | Ace Books
16.97 | Roc 8.02 Random House
5.66 | Doubleday
(4 rows)
sum()
Синтаксис:
sum (выражение)
Функция sum() получает выражение, описывающее значения любого числового типа (numeric, bigint, smallint, real или double precision), и возвращает сумму значений в группе. Для выражений типа integer результат возвращается в виде значения типа numeric, а для выражений типа real — в виде значения типа double precision. В остальных случаях тип возвращаемого значения совпадает с типом выражения.
получает выражение, описывающее значения любого
booktown=# SELECT sum(stock) FROM stock;
sum
"BOB"
(1 row)
booktown=# SELECT sum(stock). s.subject
booktown-# FROM ((stock NATURAL JOIN editions)
booktown(# JOIN books ON (books.id = bookjd))
booktown-f JOIN subjects AS s
booktown-# ON (books.subject_id = s.id)
booktown-# GROUP BY s.subject
booktown-# ORDER BY sum DESC;
189 | Horror
166 I Science Fiction
91 | Children's Books
28 | Drama
18 | Classics
16 | Arts
(6 rows)
variance()
Синтаксис: variance(выражение)
Функция variance() получает выражение, описывающее значения любого числового типа (numeric, bigint, small int, real или double precision), и возвращает дисперсию для группы (stddevO в квадрате). Для вещественных выражений результат возвращается в виде значения типа double precision, а для остальных типов — в виде значения типа numeric.
Примеры
booktown=# SELECT variance(retaiT) FROM stock;
variance
71.60
(1 row)
booktown=# SELECT varianceCretail), p.name
booktown-# FROM (stock NATURAL JOIN editions)
booktown-# JOIN publishers AS p
booktown-# ON (editions.pub!isher_id = p.id)
booktown-# GROUP BY p.name
booktown-# ORDER BY variance DESC
booktown-# LIMIT 4: variance name
288.00 | Ace Books 288.00 I Roc 64.33 !
Random House 32.00 | Doubleday
(4 rows)
получает один аргумент типа text,
booktown=# SELECT * FROM books
booktown-# WHERE title LIKE ('XRabbit1):
id i title | authorjd subjectjd
1234 | The Velveteen Rabbit | 25041 | 3
(1 row)
booktown=# SELECT * FROM books
booktown-# WHERE title LIKE
id | title | authorjd | subjectjd
4513 | Dune | 1866 | 15
25908 | Franklin in the Dark | 15990 | 2 (2 rows)
booktown=# SELECT * FROM books
booktown-# WHERE title ILIKE '«python*':
id | title | authorjd | subjectjd
41473 | Programming Python | 7805 | 4 41477
Learning Python | 7805 4
(2 rows)
lower()
Синтаксис: lower(s)
Функция SQL92 1 ower () получает один аргумент типа text, преобразует все символы строки к нижнему регистру и возвращает полученную строку в виде значения типа text.
The Cat in the Hat
booktown=# SELECT ItrimC whitespace example'):
Itrim
whitespace example (1 row)
booktown=# SELECT title. ItrimCtitle, 'TD2he ')
booktown-# FROM books booktown-# LIMIT 4:
title | Itritn
The Shining | Shining
Dune I une
2001: A Space Odyssey | 001: A Space Odyssey
The Cat in the Hat j Cat In the Hat
(4 rows)
octet_length()
Синтаксис: octetjength(s)
Функция SQL92 octetj ength() получает один аргумент s типа text, varchar или character и возвращает длину полученной строки в байтах. Возвращаемое значение относится к типу integer.
В большинстве случаев длина строки в байтах совпадает с количеством символов, хотя в расширенных кодировках не всегда, поскольку в них символ по определению может состоять из нескольких байтов.
Пример
booktown=# SELECT title, octetjength(title)
booktown-# FROM books
booktown-# ORDER BY title ASC
booktown-# LIMIT 3:
title octet Jength
2001: A Space Odyssey | 21
Bartholomew and the Oobleck | 27
Dune | 4
(3 rows)
position()
Синтаксис: position(b IN s)
Функция SQL92 position^) получает два аргумента, относящихся к типу text, и возвращает начальную позицию подстроки b в строке s (отсчет начинается с 1). Возвращаемое значение относится к типу i nteger. Если подстрока не найдена, функция возвращает 0.
The Cat in the Hat
booktown=# SELECT rtrimC'whitespace example ');
rtrim
whitespace example
(1 row)
booktown=# SELECT title, rtrinKtitle, 'yes')
booktown-# FROM books
booktown-# LIMIT 4;
title rtrim
The Shining | The Shining
Dune Dun 2001: A Space Odyssey 2001: A Space Od
The Cat in the Hat j The Cat in the Hat
(4 rows)
strpos()
Синтаксис: strpos(s. b)
Функция strposO эквивалентна функции SQL92 positionO, но аргументы передаются ей в стиле С. Функция получает два аргумента, относящихся к типу text, и возвращает начальную позицию подстроки b в строке s (отсчет начинается с 1). Возвращаемое значение относится к типу 1 nteger. Если подстрока не найдена, функция возвращает 0.
Tale Heart Heart The Shining
booktown=# SELECT title, substring(title FROM 15)
booktown-# FROM books
booktown-* ORDER BY title DESC
booktown-# LIMIT 3;
title | substring
The Velveteen Rabbit | Rabbit
The Tell- Tale Heart Heart The Shining
(3 rows)
booktown=# SELECT title, substring(title FROM 5 FOR 9)
booktown-# FROM books
booktown-# ORDER BY title DESC booktown-# LIMIT 3;
title | substring
The Velveteen Rabbit Velveteen
The Tell-Tale Heart Tell-Tale
The Shining | Shining
(3 rows)
to_ascii()
Синтаксис:
to_ascii(s, f)
Функция to_asci i () получает строковый аргумент s, относящийся к типу text, и обозначение расширенной кодировки f, а возвращает обычный ASCII-текст в виде значения типа text.
Допустимы следующие обозначения расширенных кодировок: LATIN1 (ISO 8859-1), LATIN2 (ISO 8859-2) и WIN1250 (Windows CP1250 или WinLatin2). Для работы функции необходима поддержка расширенных кодировок (устанавливается при помощи ключа командной строки компилятора при установке PostgreSQL).
получает один аргумент типа text,
booktowrH1 SELECT isbn, trim(LEADING '0' FROM isbn)
booktown-# FROM editions booktown-# LIMIT 2; isbn | Itrim
039480001X 39480001X 0451160916 451160916
(2 rows)
booktown=# SELECT isbn, trimCTRAILING 'X' FROM isbn)
booktown-# FROM editions booktown-# LIMIT 2;
1Sbn rtrim
039480001X j 039480001 0451160916 j 0451160916
(2 rows)
booktowrHf SELECT isbn, trimCBOTH 'OX' FROM isbn)
booktown-# FROM editions booktown-# LIMIT 2; isbn I btrim
039480001X | 39480001 0451160916 | 451160916
(2 rows)
upper()
Синтаксис:
upper(s)
Функция SQL92 upper() получает один аргумент типа text, преобразует все символы строки к верхнему регистру и возвращает полученную строку в виде значения типа text.
s определяет компонент, до которого
booktown=# SELECT date_part('minute'.
booktown(# intervalC3 days 4 hours 12 minutes')):
date_part
12
(1 row)
booktown=# SELECT isbn,
booktown-l date_part('year', publication)
booktown-# FROM editions
booktown-# ORDER BY date_part ASC
booktown-# LIMIT 3;
isbn | date_part
0760720002 | 1868
0679803335 | 1922
0694003611 | 1947
(3 rows)
Примечание 1
Примечание 1
Аналогом функции date_part() в SQL является функция extract().
date_trunc()
Синтаксис: date_trunc(s. t)
Функция date_trunc () получает два аргумента s и t, относящихся к типам text и timestamp соответственно. Строка s определяет компонент, до которого усекается аргумент t. В данном контексте под усечением понимается удаление всех компонентов, детализация которых превышает заданную.
Допустимые значения аргумента s перечислены в табл. 5.12.
получает один аргумент типа timestamp
booktown=# SELECT extract(MINUTE FROM
interval('3 days 12 minutes1)): datejpart
12
(1 row)
booktown=# SELECT extractCMONTH FROM now()):
date_part
8
(1 row)
isfinite()
Синтаксис:
isfinite(t) isfinite(i)
Функция 1 sf 1 ni te() получает один аргумент типа timestamp или 1 interval. Она возвращает true, если переданное значение не является бесконечным, созданным при помощи специальной константы Infinity или invalid (используется только для timestamp).
в форматной строке отсутствует последовательность
booktown=# SELECT to_char(123456789. '999G999G999D99') AS formatted,
booktown-# to_char(123456789. '999999999') AS justjrigits,
booktown-f to_char(123456789, '00999999999') AS with_zeroes;
formatted | justjrigits | with_zeroes
123.456.789.00 | 123456789 | 00123456789
(1 row)
booktown=# SELECT cost * 100 AS cost_to_order.
booktown-# to_char(cost * 100, '$99.999.99') AS monetary,
booktown-# translate(to_char(cost * 100. '$9,999.99'),' ',").
booktown-# AS translated
booktown-# FROM stock
booktown-* LIMIT 3;
cost_to_order monetary translated
2900.00 | $ 2.900.00 $2.900.00
3000.00 $ 3.000.00 $3.000.00
1600.00 $ 1,600.00 i $1.600.00
(3 rows)
booktown=# SELECT tojrhard.O. '9th "Place"') AS first.
booktown-# to_char(2.2, '9th "Place"') AS second,
booktown-# to_char(pi( ), '9th "Place"') AS third,
booktown-# to_char(10, '99V99th "\\"Place\\.....) AS shifted jjp;
first | second | third | shifted_up
1st Place | 2nd Place | 3rd Place | 1000th "Place"
(1 row)
Примечание 2
Примечание 2
В PostgreSQL версии 7.1.x ошибка в реализации метасимволов RN (римская запись) приводит к тому, что функция to_char() возвращает неправильный результат, если в форматной строке отсутствует последовательность FM. Ошибка должна быть исправлена в версии 7.2, а в качестве временной меры можно использовать полную последовательность FMRN.
to_char() для типа timestamp
Синтаксис:
to_char(t. f)
При вызове с аргументом t типа timestamp и аргументом f типа text функция to_char() форматирует дату и время в строку, возвращаемую в виде значения типа text.
Как и в случае с предыдущей версией to_char(), строка f содержит метасимволы, вместо которых PostgreSQL подставляет литералы. Метасимволы, используемые в форматных строках даты и времени, перечислены в табл. 5.15.
Приоритет операторов
Приоритет операторов
При работе с большими выражениями, содержащими несколько операторов, полезно знать, в каком порядке выполняются операторы в PostgreSQL. Было бы неправильно полагать, что операторы выполняются слева направо в порядке их следования в выражении. При неправильном понимании этой темы нередко возникают нежелательные побочные эффекты (листинг 5.18).
Сравнение с использованием ключевых слов
Сравнение с использованием ключевых слов
Ключевое слово BETWEEN (также иногда называемое оператором) позволяет проверить, входит ли значение в некоторый интервал. Например, команда SELECT, приведенная в листинге 5.11, находит книги, цена которых находится в интервале от 10 до 17 долларов.
Строковые функции
Строковые функции
В PostgreSQL существует множество разнообразных строковых функций, предназначенных для форматирования, анализа и сравнения строк. К их числу относятся как функции стандарта SQL92, так и нестандартные расширения PostgreSQL (например, ItrimO, rtrimO и substrO). Строковые функции PostgreSQL перечислены в табл. 5.10. В общем случае все, что говорится о типе text, в равной степени относится к значениям типа character и varchar.
Строковые операторы
Строковые операторы
В PostgreSQL существует обширный набор строковых операторов для выполнения различных действий, от простой конкатенации текста и сравнения строк до поиска по регулярным выражениям. Строковые операторы работают с типами char, varchar, а также с собственным типом PostgreSQL text.
Ниже описаны основные операторы сравнения и конкатенации, а также реализация операторов регулярных выражений с учетом и без учета регистра символов.
Базовые операторы сравнения
Базовые операторы сравнения строк и конкатенации, поддерживаемые в PostgreSQL, перечислены в табл. 5.1.
Примечание 1
Примечание 1
Ключевые слова LIKE и ILIKE, приводящие к вызову функции 11ke(), иногда называются операторами сравнения строк. Эти ключевые слова рассматриваются ниже в разделе «Функции».
Базовые строковые операторы
Таблица 5.1. Базовые строковые операторы
| Оператор |
Синтаксис | Описание |
| = | 'строка!' = ' строка2' | Возвращает true, если первая строка точно совпадает со второй |
| ! = | 'строка!' != ' строка2' | Возвращает true, если первая строка не совпадает со второй |
| о | 'строка!' <> ' строка2' | Идентичен оператору != |
| < | 'строка!' < ' строка2' | Возвращает true, если при лексикографической сортировке первая строка предшествует второй |
| <= | 'строка!' <= ' строка2' | Возвращает true, если при лексикографической сортировке первая строка предшествует второй или их значения совпадают |
| > | 'строка!' > ' строка2' | Возвращает true, если при лексикографической сортировке вторая строка предшествует первой |
| >= | 'строка!' >= ' строка2' | Возвращает true, если при лексикографической сортировке вторая строка предшествует первой или их значения совпадают |
booktown=# SELECT letter, ascii(letter)
booktown-# FROM text_sorting
booktown-# ORDER BY letter ASC;
letter ascii
0 48
1 49
2 50
3 51
A 65
В 66
С 67
D 68
a 97
b 98
с 99
d I 100
(12 rows)
Если вы не уверены в порядке сортировки того или иного символа, воспользуйтесь функцией ascii О для получения его ASCII-кода (функция asci i () описана ниже в разделе «Функции»). В листинге 5.3 из таблицы books выбираются названия всех книг, первая буква которых при сортировке предшествует символу «D».
Строковые функции
Таблица 5.10. Строковые функции
| Функция | Описание |
| ascii(s) | Возвращает ASCII-код символа, переданного в виде строковой переменной s |
| btrim(s [, t]) | Возвращает строку s, в начале и в конце которой удалены все символы, входящие в строку t (если аргумент t не задан, усекаются начальные и конечные пропуски — пробелы, символы табуляции и т. д.) |
| char length(s) | Возвращает длину строки s в символах |
| chr(n) | Возвращает символ с ASCII-кодом n |
| s ilike(f) | Возвращает true, если выражение f совпадает (без учета регистра символов) с s |
| imtcap(s) | Возвращает строку s, в которой первая буква каждого слова преобразуется к верхнему регистру |
| length(s) | Возвращает длину строки s в символах |
| s like(f) | Возвращает true, если выражение f совпадает с s |
| lower (s) | Возвращает строку s, преобразованную к нижнему регистру |
| lpad(s. n [. c]) | Возвращает строку s, дополненную слева содержимым строки с (или пробелами, если аргумент с не задан) до длины n (или усеченную справа до n символов) |
| ltrim(s [. f]) | Возвращает строку s, в начале которой удалены все символы, входящие в строку f (если аргумент f не задан, усекаются начальные пропуски — пробелы, символы табуляции и т. д.) |
| octet_length(s) | Возвращает длину строки s в байтах |
| pos1tion(b IN s) | Возвращает позицию подстроки b в строке s (отсчет начинается с 1) |
| repeat (s, n) | Возвращает строку s, повторенную n раз |
| rpad(s. n. [. c]) | Возвращает строку s, дополненную справа содержимым строки с (или пробелами, если аргумент с не задан) до длины n (или усеченную слева до n символов) |
| rtrim(s [. f]) | Возвращает строку s, в конце которой удалены все символы, входящие в строку f (если аргумент f не задан, усекаются конечные пропуски — пробелы, символы табуляции и т. д.) |
| strpos(s. b) | Возвращает позицию подстроки b в строке s (отсчет начинается с 1). Относится к числу функций PostgreSQL и дублирует функцию SQL positionO, но с передачей аргументов в стиле С |
| substr(s. b [. 1]) | Выделяет из строки s подстроку, начинающуюся с позиции n (отсчет начинается с 1). Необязательный аргумент 1 определяет максимальную длину подстроки в символах |
| substring FROM n FOR 1 ) |
Выделяет из строки s подстроку, начинающуюся с позиции n (отсчет начинается с 1). Необязательный аргумент 1 определяет максимальную длину подстроки в символах |
| to_ascii (s. f) | Возвращает строку s, преобразованную из расширенной кодировки f в ASCII |
| translate(s. f. r) | Возвращает строку s, в которой все символы, входящие в строку f, заменяются соответствующими символами строки г |
| trim(направление f FROM s) | Возвращает строку s, в начале и/или в конце которой удалены все символы, входящие в строку f. В аргументе направление передается ключевое слово SQL, определяющее направление усечения (LEADING, TRAILING или BOTH) |
| upper(s) | Возвращает строку s, преобразованную к верхнему регистру |
ascii()
Синтаксис: ascii(s)
Функция asci i () получает один аргумент — отдельный символ или строку типа text, и возвращает числовой ASCII-код первого интерпретированного символа. Результат возвращается в виде значения типа integer.
Функции для работы с датой и временем
Таблица 5.11. Функции для работы с датой и временем
| Функция | Описание |
| current date | Возвращает текущую дату в виде значения типа date |
| current time | Возвращает текущее время в виде значения типа time |
| current timestamp | Возвращает текущие дату и время в виде значения типа timestamp |
| date_part(s. t) | Выделяет из значения типа timestamp компонент даты или времени, определяемый строкой s |
| date_part(s. i) | Выделяет из значения типа interval компонент даты или времени, определяемый строкой s |
| date trunc(s, t) | Возвращает значение типа timestamp, усеченное до точности s |
| extract (k FROM t) | Выделяет из значения типа timestamp компонент даты или времени, определяемый ключевым словом k |
| extracttk FROM i) | Выделяет из значения типа interval компонент даты или времени, определяемый ключевым словом k |
| isfinite(t) | Возвращает true, если значение типа timestamp соответствует конечной величине (не invalid и не infinity) |
| isfinite(i) | Возвращает true, если значение типа interval соответствует конечной величине (не infinity) |
| now() | Возвращает текущие дату и время в виде значения типа timestamp. Эквивалент константы now |
| timeofdayO | Возвращает текущие дату и время в виде значения типа text |
current_date
Синтаксис:
current_date
Функция current_date вызывается без аргументов и возвращает текущую дату в виде значения типа date. Результат эквивалентен преобразованию специальной константы now к типу date.
Компоненты типов timestamp и interval
Таблица 5.12. Компоненты типов timestamp и interval
| Компонент | Описание |
| century | Год, разделенный на 100 (не совпадает с текущим веком!) |
| day | День месяца (от 1 до 31) для типа timestamp, продолжительность интервала в днях для типа interval |
| decade | Год, разделенный на 10 |
| dow | День недели (от 0 до 6), начиная с воскресенья. Для типа interval не поддерживается |
| doy | День года (от 1 до 366). Для типа interval не поддерживается |
| epoch | Количество секунд от начала эпохи (1 января 1970 г.) для типа timestamp, продолжительность интервала в секундах для типа interval |
| hour | Час в значении типа timestamp |
| microseconds | Количество миллионных долей в дробной части секунд для значения типа timestamp |
| millennium | Год, разделенный на 1000 (не совпадает с текущим тысячелетием!) |
| mi 11 i seconds | Количество тысячных долей в дробной части секунд для значения типа timestamp |
| minute | Минуты в значении типа timestamp или interval |
| month | Месяц в значении типа timestamp или остаток от деления продолжительности интервала в месяцах на 12 для типа interval |
| quarter | Квартал (от 1 до 4) для значений типа timestamp |
| second | Секунды в значении типа timestamp или interval |
| week | Номер недели в году для значений типа timestamp. В стандарте ISO-8601 первая неделя года определяется как неделя, в которую входит 4 января |
| year | Год в значении типа timestamp или interval |
Функции преобразования типов
Таблица 5.13. Функции преобразования типов
| Функция | Описание |
| t>1tfromint4(n) | Преобразует число в битовую последовательность |
| DlttOinW(b) | Преобразует битовую последовательность в десятичное представление |
| to_cnar(n. f) | Преобразует число в строку в формате f |
| to_char(t. f) | Преобразует значение типа timestamp в строку в формате f |
| to_date(s. f) | Преобразует строку в формате даты f в значение типа date |
| to_number(s. f) | Преобразует строку в формате даты f в значение типа numeric |
| to timestamp(s. f) | Преобразует строку в формате даты f в значение типа timestamp |
| timestamp(d) | Преобразует значение типа date к типу timestamp |
| timestamp(d. t) | Преобразует два значения типов date и time к типу timestamp |
Синтаксис:
bit.fromint4(n)
Функция bitfromint4() получает один аргумент п типа integer и возвращает его представление в виде битовой последовательности. Поскольку явного преобразования между двоичным и целочисленным типом не существует, преобразование десятичных данных в двоичную систему счисления должно Осуществляться специальной функцией.
Возвращаемое значение относится к типу bi t, а его длина не превышает 32 бита. Поскольку тип i nteger является знаковым, допустимые значения аргумента лежат в интервале от -2 147 483 648 до 2 147 483 647.
Метасимволы форматирования чисел
Таблица 5.14. Метасимволы форматирования чисел
| Символ | Описание |
| 9 | Цифра |
| 0 | Цифра или начальный/конечный ноль, если количество цифр в f превышает количество цифр в п; может использоваться для принудительного вывода цифр в левой или правой части результата |
| . | Точка, отделяющая целую часть числа от дробной. Число может содержать только одну точку |
| ' | Запятая. Число может содержать несколько запятых, используемых для разделения групп разрядов (тысячи, миллионы и т. д.) |
| D | Десятичный разделитель (например, точка), определяемый в локальном контексте |
| G | Разделитель групп разрядов (например, запятая), определяемый в локальном контексте |
| PR | Если PR находится в конце строки f, для отрицательных значений п результат заключается в угловые скобки |
| SG | Знак плюс (+) или минус (-) в зависимости от значения п |
| MI | Знак минус (-), если число п является отрицательным |
| PL | Знак плюс (+), если число п является положительным |
| S | Знак плюс (+) или минус (-), определяемый в локальном контексте |
| L | Денежный знак, определяемый в локальном контексте |
| RN | Римские цифры для значений п в интервале от 1 до 3999 |
| TH. th | Суффикс числительного для числа п (например, 4th или 2nd) |
| V | Для каждого метасимвола 9 после V добавляется лишний ноль, то есть фактически происходит умножение на степень 10 |
| FM | Из числа удаляются все начальные и завершающие нули (созданные символами 9, но не 0), а также все лишние пробелы |
Если количество заданных цифровых позиций меньше необходимого для представления целой части числа, преобразование становится неоднозначным из-за потери значащих цифр. Поскольку функция to_char() не знает, какие именно цифры следует удалить, во всех заданных позициях выводится символ #. Следовательно, в форматную строку необходимо включить максимальное количество цифр, кото-
рые могут быть получены в результате форматирования. Для удаления лишних пробелов также можно воспользоваться функцией trans! ate() или функциями усечения (HrimO и т. д.).
Чтобы метасимвол интерпретировался в форматной строке буквально (то есть как литерал), заключите его в кавычки. Чтобы включить в форматную строку литеральный символ кавычки, его необходимо экранировать двумя обратными косыми чертами.
Примечание 1
Примечание 1
В форматной строке можно свободно использовать любые символы, не являющиеся метасимволами (например, символ $ и др.) В отформатированной строке они выводятся без изменений.
Метасимволы форматирования чисел
Таблица 5.15. Метасимволы форматирования чисел
| Символ | Описание |
| НН. НН12 | Час (от 1 до 12) |
| НН24 | Час (от 0 до 23) |
| Ml | Минуты (от 0 до 59) |
| SS | Секунды (от 0 до 59) |
| SSSS | Секунды, прошедшие с полуночи (от 0 до 86 399) |
| AM, РМ, А.М, Р.М | Обозначение части суток в верхнем регистре с необязательным разделением символов точками |
| am, pm, a . m, p . m | Обозначение части суток в нижнем регистре с необязательным разделением символов точками |
| TZ, tz | Часовой пояс в верхнем или нижнем регистре |
| CC | Век, представленный двумя цифрами (не равен тку, деленному на 100!) |
| Y, YY, YYY, YYYY, Y.YYY | Последняя цифра, две цифры, три или четыре цифры года (с необязательным включением запятой) |
| BC, AD, B.C, A.O | Признак эры в верхнем регистре |
| be, ad, b.c, a.d | Признак эры в нижнем регистре |
| MONTH, Month, month | Полное название месяца, дополненное справа пробелами до 9 символов и записанное либо в верхнем регистре, либо с начальной прописной буквой, либо в нижнем регистре |
| MON, Mon, mon | Сокращенное трехбуквенное обозначение месяца, записанное либо в верхнем регистре, либо с начальной прописной буквой, либо в нижнем регистре |
| MM | Номер месяца (от 1 до 12) |
| RN, rn | Номер месяца в римской записи (от I до XII), в верхнем или нижнем регистре |
| DAY, Day, day | Полное название дня недели, дополненное справа пробелами до 9 символов и записанное либо в верхнем регистре, либо с начальной прописной буквой, либо в нижнем регистре |
| DY, Dy, dy | Сокращенное двухбуквенное обозначение дня недели, записанное либо в верхнем регистре, либо с начальной прописной буквой, либо в нижнем регистре |
| DDD, DD, D | День года (от 1 до 366), день месяца (от 1 до 31) или день недели (от 1 до 7, начиная с воскресенья) |
| W | Неделя месяца (от 1 до 5, с первого дня месяца) |
| WW | Неделя года (от 1 до 53, с первого дня года) |
| IW | Неделя года в стандарте ISO (с первого четверга нового года) |
| TH, th | Суффикс для предшествующего числа в верхнем или нижнем регистре |
| fm | Из строки удаляются все лишние нули и пробелы |
Агрегатные функции
Таблица 5.16. Агрегатные функции
| Функция | Описание |
| avg( выражение') | Возвращает среднее арифметическое значений выражения для всех записей в группе |
| count ( выражение) | Возвращает количество записей в группе, для которых значение выражения отлично от NULL |
| ma x ( выражение} | Возвращает максимальное значение выражения в группе |
| mint выражение) | Возвращает минимальное значение выражения в группе |
| stddev ( выражение) | Возвращает среднеквадратичное отклонение значений выражения в группе |
| surrK выражение) | Возвращает сумму значений выражения в группе |
| variance( выражение) | Возвращает дисперсию значений выражения в группе |
Операторы регулярных выражений
Таблица 5.2. Операторы регулярных выражений
| Оператор | Синтаксис | Описание |
| - | ' строка' ~ ' выражение' | Возвращает true, если в строке существует совпадение для регулярного выражения |
| i ~ | 'строка' \- 'выражение' | Возвращает true, если в строке нет совпадения для регулярного выражения |
| ~* | ' строка' ~* ' выражение' | Возвращает true, если в строке существует совпадение для регулярного выражения (без учета регистра символов) |
| |_* | 'строка' !-* 'выражение' | Возвращает true, если в строке нет совпадения для регулярного выражения (без учета регистра символов) |
Метасимволы регулярных выражений
Таблица 5.3. Метасимволы регулярных выражений
| Символ | Синтаксис | Описание |
| - | ^выражение | Соответствует началу строки |
| $ | выражение$ | Соответствует концу строки |
| . | , | Соответствует одному символу |
| [ ] | [abc] | Соответствует любому из символов, перечисленных в квадратных скобках |
| Г] | ГаЬс] | Соответствует любому символу кроме символов, перечисленных в квадратных скобках |
| [-] | [a-z] | Соответствует любому символу из интервала, заданного в квадратных скобках |
| Г-] | Га-z] | Соответствует любому символу кроме символов из интервала, заданного в квадратных скобках |
| 7 | а? | Соответствует нулю экземпляров или одному экземпляру предшествующего символа или подвыражения |
| * | а* | Соответствует нулю экземпляров или произвольному количеству экземпляров предшествующего символа или подвыражения |
| + | а+ | Соответствует одному и более экземпляров предшествующего символа или подвыражения |
| 1 | выражение! \ выражение2 | Соответствует левому или правому подвыражению |
| ( ) | (выражение!) выражение2 | Группировка подвыражений с явным определением приоритета выполняемых операций |
Примечание 3
Литералы, совпадающие с метасимволами из табл. 5.3, должны экранироваться в строке двумя символами \ (например, знак $ представляется последовательностью \\$).
Регулярные выражения часто применяются для поиска подстрок в строках-литералах большего размера. При поиске соответствия с учетом регистра символов используется оператор -; с оператором -* регистр игнорируется. Примеры приведены в листинге 5.6.
Математические операторы
Таблица 5.4. Математические операторы
| Оператор | Синтаксис | Описание |
| + | а + b | Суммирование числовых величин а и b |
| - | а - Ь | Вычитание числовой величины b из а |
| * | а * b | Умножение числовых величин а и b |
| / | а / b | Деление числовой величины а на b |
| % | а % b | Остаток от деления а на b |
| А | а - b | Возведение а в степень b |
| |/ | !/ а | Квадратный корень из а |
| II/ | ||/ а | Кубический корень из b |
| 1 | а! | Факториал а |
| ! 1 | !! а | Факториал а (отличается от постфиксного оператора только расположением) |
| @ | @ а | Модуль (абсолютное значение) а |
Операторы сравнения
Таблица 5.5. Операторы сравнения
| Оператор | Описание |
| < | Возвращает true, если левое значение меньше правого |
| > | Возвращает true, если левое значение больше правого |
| <= | Возвращает true, если левое значение меньше правого или равно ему |
| >= | Возвращает true, если левое значение больше правого или равно ему |
| = | Возвращает true, если левое значение равно правому |
| <> или ! = | Возвращает true, если левое значение не равно правому |
Примечание 1
Оператор <> существует как синоним оператора != для обеспечения совместимости с другими реализациями СУБД на базе SQL. Работают эти операторы одинаково.
Пример команды, в которой используются операторы сравнения, приведен в листинге 5.10.
Двоичные операторы
Таблица 5.6. Двоичные операторы
| Оператор | Синтаксис | Описание |
| & | а & b | Поразрядная конъюнкция двоичных представлений а и b (которые могут быть заданы в виде целых чисел) |
| 1 | а | b | Поразрядная дизъюнкция двоичных представлений а и b (которые могут быть заданы в виде целых чисел) |
| f | а # b | Поразрядная операция исключающей дизъюнкции двоичных представлений а и b (которые могут быть заданы в виде целых чисел) |
| - | - b | Поразрядное отрицание, возвращает инвертированную битовую последовательность b |
| « | b « n | Сдвиг b влево на n разрядов |
| » | b » n | Сдвиг b вправо на n разрядов |
Операторы AND OR и NOT
Таблица 5.7. Операторы AND, OR и NOT
| а | b | aANDb | aORb | NOT a | NOTb |
| true | true | true | true | false | false |
| true | false | false | true | false | true |
| true | NULL | NULL | true | false | NULL |
| false | false | false | false | true | true |
| false | NULL | false | NULL | true | NULL |
| NULL | NULL | NULL | NULL | NULL | NULL |
Во втором запросе те же условия объединяются ключевым словом AND. В результате записи проходят более жесткий отбор, поскольку должны выполняться сразу оба критерия. Итоговый набор состоит всего из одной записи для книги, которая стоит дороже 30 долларов и отсутствует на складе.
Приоритет операторов SQL
Таблица 5.8. Приоритет операторов SQL
| Оператор | Синтаксис | Описание |
| значение: : тип | Явное преобразование типа | |
| [ ] | значение^ индекс] | Индексация элемента массива |
| таблица, поле | Разделитель имен таблицы и столбца | |
| - | -значение | Унарный минус |
| А | основание * степень | Возведение в степень |
| * / % | значение! * значение2 | Умножение, деление и остаток |
| + - | значение! + значение2 | Сложение и вычитание |
| IS | значение IS признак | Сравнение с true или false |
| IS NULL | значение IS NULL | Сравнение с NULL |
| IS NOT NULL | значение IS NOT NULL | Проверка несовпадения с NULL |
| Прочее | — | Все остальные пользовательские и встроенные операторы, не входящие ни в одну из категорий |
| IN | значение IN набор | Проверка принадлежности к заданному набору |
| BETWEEN | значение BETWEEN a AND b | Проверка принадлежности к интервалу [а. Ь] |
| LIKE, ILIKE | строка LIKE, шаблон | Проверка совпадения шаблона со строкой |
| <><=>= | значение! < значение2 | Сравнения по критериям «меньше», «больше», «меньше либо равно», «больше либо равно» |
| = | значение! = значение2 | Проверка равенства |
| NOT | NOT значение | Логическое отрицание |
| AND | значение! AND значение2 | Логическая конъюнкция |
| OR | значение! OR значение2 | Логическая дизъюнкция |
Примечание 1
Приоритет операторов, приведенных в табл. 5.8, распространяется на пользовательские операторы, обозначения которых совпадают с обозначениями встроенных операторов. Например, если вы определите собственный оператор + для своего типа данных, он будет обладать таким же приоритетом, как встроенный оператор +, независимо от своего предназначения.
Математические функции PostgreSQL
Таблица 5.9. Математические функции PostgreSQL
| Функция | Описание |
| abs(x) | Возвращает модуль (абсолютное значение) х |
| acos(x) | Возвращает арккосинус х |
| asin(x) | Возвращает арксинус х |
| atan(x) | Возвращает арктангенс х |
| atan2(x.y) | Возвращает арктангенс х/у |
| cbrt(x) | Возвращает кубический корень х |
| ceil (x) | Возвращает минимальное целое число, не меньшее х (округление в верхнюю сторону) |
| cos(x) | Возвращает косинус х |
| cot(x) | Возвращает котангенс х |
| degrees(r) | Возвращает количество градусов в г радиан |
| exp(x) | Возвращает константу е (2,71828...) в степени х |
| floor(x) | Возвращает максимальное целое число, не большее х (округление в нижнюю сторону) |
| ln(x) | Возвращает натуральный логарифм х (функция, обратная ехр(х)) |
| log(b.x) | Возвращает логарифм х по основанию b |
| log(x) | Возвращает десятичный логарифм х |
| modtx.yj | Возвращает остаток от деления х/у |
| pi О | Возвращает константу к (3,14159...) |
| pow(x.y) | Возвращает х в степени у |
| radians(d) | Возвращает количество радиан в d градусов |
| ranaomO | Возвращает псевдослучайное число в интервале от 0,0 до 1,0 |
| round(x) | Возвращает число х, округленное до ближайшего целого |
| sin(x) | Возвращает синус х |
| sqrt(x) | Возвращает квадратный корень х |
| tan(x) | Возвращает тангенс х |
| trunc(x) | Возвращает целую часть х |
| trunc(x.s) | Возвращает значение х, усеченное до s цифр в дробной части |
abs(x)
Синтаксис:
abs(x)
Функция abs() получает один числовой аргумент х и возвращает его модуль, то есть расстояние до нуля. Положительные числа остаются без изменений, а отрицательные числа меняют знак.
Аргумент функции abs() может относиться к любому из числовых типов данных (numeric, bigint, small int, real или double precision). Тип возвращаемого значения совпадает с типом аргумента.
Нетривиальные возможности
Автоматизация стандартных процедур
Автоматизация стандартных процедур
PostgreSQL является объектно-реляционной СУБД, что позволило включить в нее ряд нестандартных расширений SQL. Часть этих расширений связана с автоматизацией часто выполняемых операций с базами данных.
В этом разделе описаны две категории расширений: последовательности и триггеры.
Добавление ограничений в существующую таблицу
Добавление ограничений в существующую таблицу
Команда ALTER TABLE позволяет включать ограничения в существующую таблицу. Впрочем, в PostgreSQL 7.1.x поддерживается только возможность добавления ограничений CHECK и FOREIGN KEY.
Установка ограничений в команде ALTER TABLE имеет следующий синтаксис:
ALTER TABLE таблица
ADD [ CONSTRAINT ограничение ] { CHECK ( условие ) | FOREIGN KEY ( поле [. ... ] )
REFERENCES таблица [ ( поле [....])]
[ MATCH FULL | MATCH PARTIAL ]
[ ON DELETE операция ]
[ ON UPDATE операция ]
[ DEFERRABLE | NOT DEFERRABLE ]
[ INITIALLY DEFERRED INITIALLY IMMEDIATE ] }
В листинге 7.9 устанавливается новое ограничение FOREIGN KEY для поля subjected, которое связывается с полем id таблицы subjects. Ограничение гарантирует, что в результате вставки или обновления данных в поле subjected таблицы books не появятся значения, отсутствующие в поле id таблицы subjects.
Функциональные индексы
Функциональные индексы
В слегка измененном виде команда CREATE INDEX позволяет индексировать данные не по значениям поля, а по некоторой функции этих значений. Такая форма индекса называется функциональной.
Команда создания функционального индекса имеет следующий синтаксис:
CREATE [ UNIQUE ] INDEX индекс ON таблица
[ USING тип ] ( функция ( поле [. ...])[ класс ] )
Единственное отличие этой команды от описанной выше заключается в том, что индекс строится по результатам применения функции к каждому значению поля. Остальные элементы те же.
Функциональные индексы часто строятся для полей, значения которых проходят предварительную обработку перед сравнением в команде SQL. Например, при сравнении строковых данных без учета регистра символов часто используется функция иррегО. Создание функционального индекса с функцией иррегО улучшает эффективность таких сравнений.
В листинге 7.5 приведен пример построения индекса upper_title для таблицы books. Данные индексируются по результатам применения функции upper () к полю title. Затем выполняется запрос SQL, который благодаря наличию функционального индекса выполняется более эффективно.
Индексы элементов
Индексы элементов
Популярность массивов в значительной степени обусловлена тем фактом, что к отдельным элементам можно обращаться при помощи индексов — целых чисел, заключенных в скобки и описывающих позицию искомого элемента в массиве.
В отличие от таких языков программирования, как С, в PostgreSQL индексация в массивах начинается с 1, а не с 0. Так, в листинге 7.21 индекс [1] для поля books таблицы favorite_books описывает первый элемент массива. Обратите внимание: данные, возвращаемые запросом, не заключаются в кавычки или фигурные скобки. Это связано с тем, что отдельное текстовое значение должно возвращаться в виде одной текстовой константы, а не массива.
Индексы
Индексы
Индексом называется объект базы данных, позволяющий значительно повысить скорость обращения к базе за счет ускоренной обработки команд, содержащих сравнительные критерии. Хранимая в индексах информация о размещении данных по одному или нескольким полям таблицы повышает эффективность поиска записей при условной выборке (например, с использованием секции WHERE).
Существует несколько разновидностей внутреннего устройства индексов. В этом разделе описаны разные типы индексов, а также объясняется, в каких ситуациях следует использовать тот или иной тин.
Индексы ускоряют доступ к базе, но они также сопряжены с дополнительными затратами ресурсов. При изменении данных в поле индекс приходится обновлять, поэтому поддержание редко используемых индексов отрицательно сказывается на быстродействии системы (затраты времени на поддержание индексов превышают экономию от их использования). Как правило, индексы определяются только для полей, часто указываемых в условиях поиска.
Использование курсоров
Использование курсоров
Курсор SQL в PostgreSQL представляет собой доступный только для чтения указатель на итоговый набор выполненной команды SELECT. Курсоры часто используются в приложениях, хранящих информацию о состоянии подключения к серверу PostgreSQL. Создание курсора и работа со ссылкой на полученный итоговый набор позволяет приложению организовать более эффективную выборку разных записей итогового набора без повторного выполнения запроса с другими значениями LIMIT и OFFSET.
В прикладных интерфейсах (API) курсоры часто используются для объединения нескольких запросов с последующим их отслеживанием и управлением ими через ссылку на курсор на уровне приложения. Тем самым предотвращается необходимость хранения всех результатов в памяти приложения.
Курсоры часто обладают абстрактным представлением в прикладных интерфейсах (пример — класс PgCursor в libpq++), хотя приложение может напрямую создавать курсоры и работать с ними при помощи стандартных команд SQL. В этом подразделе описаны обобщенные принципы работы с курсорами в SQL, продемонстрированные на примере клиента psql. В PostgreSQL существуют четыре команды, предназначенные для работы с курсорами: DECLARE, FETCH, MOVE и CLOSE.
Команда DECLARE определяет и одновременно открывает курсор, после чего заполняет его информацией по результатам итогового набора выполненного запроса. Команда FETCH позволяет получить записи из открытого курсора. Команда MOVE перемещает «текущую» позицию курсора в итоговом наборе, а команда CLOSE закрывает курсор.
Примечание 1
Примечание 1
Если вас интересует тема использования курсоров в конкретном интерфейсе API, обращайтесь к документации на API.
Использование производных таблиц
Использование производных таблиц
Связь общих полей базовой и производной таблиц не ограничивается чисто косметическими удобствами. Данные, занесенные в таблицу distinguished_authors, присутствуют и в родительской таблице authors. Впрочем, в таблице authors видны только три унаследованных поля. В запрос к базовой таблице можно включить ключевое слово ONLY, которое указывает, что данные производных таблиц исключаются из результатов запроса.
Примечание 2
Примечание 2
Вставка данных в производную таблицу
booktown=# INSERT INTO distinguished_authors
booktown-# VALUES (nextvaK 'authorjds'),
booktown(# 'Simon'. 'Neil', 'Pulitzer Prize');
INSERT 3629421 1
Поскольку первые три поля таблицы di sti ngui shed_authors были унаследованы от таблицы authors, данные этой записи косвенно включаются в таблицу authors (хотя непосредственная вставка в таблицу authors не выполнялась). Тем не менее поле award будет присутствовать только в таблице di sti ngui shed_authors, поскольку наследование действует только в одну сторону (от родителя к потомку).
В листинге 7.13 выполняются три команды SELECT. В секциях FROM указываются разные цели, тогда как условия в секциях WHERE всех трех команд одинаковы.
Построение индекса
Листинг 7.1. Построение индекса
booktown=# CREATE INDEX books_title_idx
booktown-# ON books (title);
CREATE
booktown=# \d books
Table "books" Attribute | Type | Modifier
id | integer | not null
title | text | not null
authorjd |integer |
subjectjd I integer
Indices: books_id_pkey. books_titlejdx
Установка некоторых типов ограничений (прежде всего, ограничения PRIMARY KEY и UNIQUE) также приводит к автоматическому построению индекса. В листинге 7.2 при создании таблицы authors для поля id устанавливается ограничение первичного ключа (PRIMARY KEY). В результате автоматически строится индекс authors_pkey.
Удаление ограничений
Листинг 7.10. Удаление ограничений
booktown=*# DROP INDEX books_id_pkey;
DROP
booktown=# CREATE TABLE new_books
booktown-# (id integer CONSTRAINT books_id_pkey PRIMARY KEY.
booktown(# title text NOT NULL.
booktown(# author_id integer.
booktown(# subjected integer):
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'books_id_pkey'
for table 'new_books'
CREATE
booktown=# INSERT INTO new_books SELECT * FROM books:
INSERT 0 15
booktown=f ALTER TABLE books RENAME TO old_books:
ALTER
booktown=# ALTER TABLE new_books RENAME TO books;
ALTER
Создание производной таблицы
Листинг 7.11. Создание производной таблицы
booktown=# CREATE TABLE distinguished_authors (award text)
booktown-# INHERITS (authors): CREATE
booktown=# \d distinguished_authors Table "distinguished_authors"
Attribute | Type Modifier
id | integer | not null
lastjiame text |
firstjiame | text
award text
Как видите, несмотря на то что в листинге 7.11 определено всего одно поле, таблица distinguished_authors унаследовала все поля исходной таблицы authors.
Выборка с наследованием
Листинг 7.13. Выборка с наследованием
booktown=# SELECT * FROM distinguished_authors
booktown-# WHERE lastjiame - 'Simon';
id | last_name firstjname award
25043 | Simon | Neil | Pulitzer Prize
(1 row)
booktown=# SELECT * FROM authors WHERE last_name - 'Simon';
Id last_name first_name
25043 | Simon | Neil (1 row)
booktown=# SELECT * FROM ONLY authors WHERE
lastjname = 'Sinon': id i last_name | first_name
(0 rows)
Все три запроса в листинге 7.13 производят выборку записей, у которых поле 1 astjname совпадает со строковой константой Simon. Первый запрос извлекает данные из таблицы distinguished_authors, в которую они были первоначально занесены (см. листинг 7.12).
Второй запрос в листинге 7.13 производит выборку из таблицы authors, базовой по отношению к distinguished_authors. В этом случае запись также возвращается, но в нее включаются только поля, унаследованные таблицей di st i ngui shed_authors.
Следует хорошо понимать, что данные в действительности не заносятся в базовую таблицу, а лишь становятся видимыми в ней благодаря отношению наследования. Это доказывает третий и последний запрос в листинге 7.13, в котором перед именем таблицы authors находится ключевое слово ONLY. Оно означает, что выборка производится только из базовой таблицы, а производные таблицы игнорируются; в результате запрос не возвращает ни одной записи.
Наследование может приводить к видимому нарушению ограничений. Например, значение поля, для которого установлено ограничение уникальности, может повторяться в данных производных таблиц. Применение наследования требует осторожности, поскольку производная таблица формально не нарушает ограничений, хотя при выборке из базовой таблицы без ключевого слова ONLY может показаться обратное.
Модификация базовых и производных таблиц
Листинг 7.14. Модификация базовых и производных таблиц
booktown=# UPDATE authors SET firstjiame - 'Paul'
booktown-# WHERE last_name = 'Simon';
UPDATE 1
booktown=# SELECT * FROM distinguished_authors;
id | lastjiame first_name award ---25043
Simon | Paul Pulitzer Prize
(1 row)
Ключевое слово ONLY выполняет в командах UPDATE и DELETE те же функции, что и в команде SELECT — оно предотвращает каскадные модификации, продемонстрированные в листинге 7.14. Согласно правилам синтаксиса SQL ключевое слово ONLY всегда предшествует имени производной таблицы.
Пример использования ключевого слова ONLY приведен в листинге 7.15. Сначала в таблице distinginshed_authors создается запись, в которой заполняется поле award. В результате в таблице authors появляются две разные записи для одного автора. Затем старая запись (физически находящаяся в таблице authors) удаляется командой SQL DELETE с ключевым словом ONLY.
Модификация базовых
Листинг 7.15. Модификация базовых таблиц с ключевым словом ONLY
booktown=# INSERT INTO distinguished_authors
booktown-* VALUES (1809. 'Geisel'.
booktown(# 'Theodor Seuss', 'Pulitzer Prize');
INSERT 3629488 1
booktown=# SELECT * FROM authors
booktown-# WHERE lastjname = 'Geisel':
id | lastjname | firstjiame
1809 | Geisel | Theodor Seuss 1809 | Geisel |
Theodor Seuss
(2 rows)
booktown=# DELETE FROM ONLY authors
booktown-# WHERE lastjiame = 'Geisel';
DELETE 1
В итоге после выполнения листинга 7.15 запись появляется в таблице distinguished_authors и удаляется из таблицы authors:
booktown=# SELECT * FROM authors
booktown-# WHERE lastjiame = 'Geisel':
id | lastjiame | firstjiame
1809 Geisel | Theodor Seuss
(1 row)
booktown=# SELECT * FROM distinguishedjauthors
booktown-# WHERE lastjiame = 'Geisel1;
id | lastjiame | firstjiame | award
1809 | Geisel | Theodor Seuss | Pulitzer Prize
(1 row)
Создание таблицы с полеммассивом
Листинг 7.16. Создание таблицы с полем-массивом
booktown=# CREATE TABLE favorite_books
booktown-# (employeejid integer, books text[]);
CREATE
Таблица, созданная в листинге 7.16, позволяет хранить в одном поле неограниченное количество названий книг. Преимущество массива перед объединением названий в одну строку (которая, конечно, тоже может содержать несколько названий) заключается в их физической изоляции. Система знает, где начинается и где кончается каждое название, поэтому выборка может производиться по индексу элемента вместо ручного разбора длинной строки на составляющие.
Многомерные массивы создаются аналогичным образом, просто за первой парой квадратных скобок добавляются дополнительные пары. В листинге 7.17 создается таблица favorite_authors с целочисленным полем employee_id и многомерным массивом author_and_titles. Фактически мы создаем массив текстовых массивов.
Создание таблицы
Листинг 7.17. Создание таблицы с полем, содержащим многомерный массив
booktown=# CREATE TABLE favorite_authors (employee_id Integer,
booktowntf authors_and_titles text[][]);
CREATE
Вставка с использованием массивовконстант
Листинг 7.18. Вставка с использованием массивов-констант
booktown=# INSERT INTO favorite_books VALUES
booktown-# (102, '{"The HitchhikerVs Guide to the Galaxy"}');
INSERT 3628399 1
booktown=# INSERT INTO favorite_books VALUES
booktown-# (103, '{"The Hobbit". "Kitten, Squared"}');
INSERT 3628400 1
Как видно из листинга, даже при вставке одного элемента массив заключается в фигурные скобки. Кроме того, обратите внимание, что апостроф в названии книги (первая команда INSERT) экранируется символом \, хотя и находится внутри кавычек. Это связано с тем, что массив-константа сначала обрабатывается как одна длинная строка, а затем интерпретируется как массив по контексту целевого поля.
При вставке значений в многомерный массив все подмассивы заключаются в отдельные фигурные скобки и разделяются запятыми. В листинге 7.19 приведен пример вставки одной записи с многомерным массивом-константой в таблицу favorite_authors, созданную в листинге 7.17.
Вставка данных в многомерный массив
Листинг 7.19. Вставка данных в многомерный массив
booktown=# INSERT INTO favorite_authors
bOOktown-# VALUES (102,
booktown(# '{{"J.R.R. Tolkien". "The Silmarillion"},
booktown'# {"Charles Dickens", "Great Expectations"},
booktown'l {"Ariel Denham", "Attic Lives"}}');
INSERT 3727961 1
Многомерный массив в листинге 7.19 содержит три текстовых массива, каждый из которых состоит из двух элементов. Между массивами не существует никаких систематических связей, хотя из контекста следует, что первые элементы каждого массива обозначают авторов, а вторые элементы обозначают названия книг, написанных этими авторами.
Автоматическое построение индекса
Листинг 7.2. Автоматическое построение индекса
booktown=# CREATE TABLE authors (id integer PRIMARY KEY,
booktown(# last_name text,
booktown(# first_name text);
NOTICE: CREATE TABtE/PRIMARY KEY will create implicit index 'authors_pkey' for
table 'authors'
CREATE
example=# \d authors
Table "authors"
Attribute | Type Modifier
id integer | not null
lastjiame | text
firstjiame text |
Index: authors_pkey
Индекс, построенный командой из листинга 7.2, позволяет PostgreSQL быстро проверять уникальность первичного ключа для всех новых записей, заносимых в таблицу. Кроме того, индекс повышает скорость выполнения запросов, у которых поле i d указано в условии поиска.
Выборка из полеймассивов
Листинг 7.20. Выборка из полей-массивов
booktown=# SELECT books FROM favorite_books;
books
{"The Hitchhiker's Guide to the Galaxy"}
{"The Hobbit"."Kitten. Squared")
(2 rows)
Хотя возможность выборки всего массива приносит несомненную пользу, на практике чаще требуется получить некоторое подмножество элементов. Для решения этой задачи необходимо познакомиться с такими новыми понятиями, как индексы элементов и срезы массивов.
Выборка отдельного элемента массива
Листинг 7.21. Выборка отдельного элемента массива
booktown=# SELECT books[l] FROM favorite_books:
books
The Hitchhiker's Guide to the Galaxy The Hobbit
(2 rows)
При указании индекса несуществующего элемента массива выборка возвращает NULL. Обычно для обработки таких ситуаций используется конструкция IS NOT NULL. В листинге 7.22 приведены два запроса; первый возвращает две записи — для NULL и для названия книги. Второй запрос возвращает только название, а запись с NULL исключается из выборки в результате использования секции WHERE с проверкой условия NOT NULL.
Предотвращение выборки NULL в массивах
Листинг 7.22. Предотвращение выборки NULL в массивах
booktown=# SELECT books[2] FROM favorite_books;
books
Kitten. Squared (2 rows)
booktown=# SELECT books[2] FROM favorite_books
booktown-# WHERE books[2] IS NOT NULL;
books
Kitten. Squared
(1 row)
При выборке из многомерного массива за исходным индексом перечисляются дополнительные индексы. В листинге 7.23 из таблицы favorite_authors, созданной в листинге 7.19, выбираются два элемента — имя автора и название книги.
Выборка из многомерного массива
Листинг 7.23. Выборка из многомерного массива
booktown=# SELECT authors_and_titles[l][l] AS author,
booktown-# authors_and_titles[l][2] AS title
booktown-# FROM favorite authors;
author I title
J.R.R. Tolkien | The Silmarillion
(1 row)
Выборка с использованием среза
Листинг 7.24. Выборка с использованием среза
booktown=# SELECT books[l:2] FROM favorite_books;
books
{"The Hitchhiker's Guide to the Galaxy"}
{"The Hobbit"."Kitten, Squared"}
(2 rows)
В PostgreSQL 7.1.x использование срезов в многомерных массивах иногда приводит к непредсказуемым последствиям. По этой причине, пока не будут внесены исправления, при работе с многомерными массивами рекомендуется обращаться к элементам по конкретным значениям индексов.
Функция array_dims()
Листинг 7.25. Функция array_dims()
booktown=# SELECT array_dims(books) FROM favorite_books;
array_dims
[1:1]
[1:2]
(2 rows)
Обновление данных в полях-массивах
Существует три варианта модификации данных в полях-массивах.
- Полная модификация. Все содержимое массива заменяется новыми данными, заданными в виде массива-константы.
- Модификация среза. Срез (то есть интервальное подмножество элементов) заменяется новыми данными, заданными в виде массива-константы. Количествоэлементов в константе должно соответствовать количеству элементов в обновляемом срезе.
- Модификация элемента. Отдельный элемент массива заменяется новой константой, относящейся к базовому типу данных массива. Элемент задается индексом. В первом случае количество элементов в новом массиве может не совпадать с количеством элементов в существующем массиве. Допустим, работник с кодом 1d=102 хочет добавить данные о новой книге в список, хранящийся в таблице favorite_books. Команда UPDATE, приведенная в листинге 7.26, заменяет все текущее содержимое массива.
Полная модификация массива
Листинг 7.26. Полная модификация массива
booktown=# UPDATE favorite_books
booktown-# SET books='{"The HitchhikerVs Guide to the Galaxy",
booktown'# "The Restaurant at the End of the Universe"}'
booktown-# WHERE employeejd = 102;
UPDATE 1
Способ, продемонстрированный в листинге 7.26, подходит и для модификации среза массива. Для этого в конец идентификатора поля добавляется определение среза, например, books[l:3] означает первый, второй и третий элементы массива. Впрочем, на практике чаще возникает задача замены не всего массива и не среза, а отдельных элементов.
При обновлении отдельного элемента к идентификатору поля присоединяется индекс, определяющий конкретный обновляемый элемент*. В листинге 7.27 приведен пример обновления первого элемента в массиве books таблицы favorite_books.
Модификация отдельного элемента
Листинг 7.27. Модификация отдельного элемента
booktown=# SELECT books[l] FROM favorite_books;
books
The Hitchhiker's Guide to the Galaxy The Hobbit
(2 rows)
booktown=# UPDATE favorite_books
booktown-# SET books[l] = 'There and Back Again: A HobbitVs Holiday'
booktown-# WHERE books[l] = 'The Hobbit';
UPDATE 1
booktown=# SELECT books[l] FROM favorite_books;
books
The Hitchhiker's Guide to the Galaxy
There and Back Again: A Hobbit's Holiday
(2 rows)
Создание последовательности
Листинг 7.28. Создание последовательности
booktown-# CREATE SEQUENCE shipments_ship_id_seq
booktown-# MINVALUE 0;
CREATE
Вывод атрибутов последовательности
Листинг 7.29. Вывод атрибутов последовательности
booktown=# SELECT 1ast_value, increment_by
booktown-# FROM shipments_ship_id_seq;
last_value increment_by
0 | 1
(1 row)
Запрос обращен к только что созданной последовательности, поэтому атрибут 1 ast_val ue остался равным нулю.
Создание уникального индекса
Листинг 7.3. Создание уникального индекса
booktown-* CREATE UNIQUE INDEX unique_publisherjdx
booktown-# ON publishers (name):
CREATE
booktown=# \d publishers
Table "publishers" Attribute | Type | Modifier
id integer | not null
name | text
address j text j Indices: publishers_pkey.
urn que_publ i sher_i dx
Поскольку псевдозначение NULL формально не совпадает ни с одним реальным значением, в поле с уникальным индексом допускаются многократные вхождения NULL. В этом и заключается главное практическое различие между уникальным индексом и индексом, автоматически создаваемым при установке ограничения PRIMARY KEY, которое вообще запрещает присутствие значений NULL.
ВНИМАНИЕ
Ключевое слово UNIQUE в сочетании с секцией USING может использоваться только для индексов, реализованных в виде В-дерева.
Изменение текущего значения последовательности
Листинг 7.30. Изменение текущего значения последовательности
booktown=# SELECT nextvaH 'shipments_shipjd_seq');
nextval
1 (1 row)
booKtown=# SELECT nextval ('shipments_ship_id_seq'):
nextval
2
(1 row)
Примечание 1
Примечание 1
При первом вызове функция nextval О возвращает начальное значение последовательности (заданное с ключевым словом START). Причина — функция не вызывалась, поэтому приращение еще не произошло. При всех последующих вызовах nextval () атрибут last_value изменяется.
Последовательности часто используются при определении значений по умолчанию для таблиц, в которых должны храниться уникальные целочисленные идентификаторы. Пример приведен в табл. 7.2.
Функция currval()
Листинг 7.31. Функция currval()
booktown=# INSERT INTO shipments (customer_id, isbn, ship_date)
booktown-# VALUES (221. '0394800753', 'now');
INSERT 3628625 1
booktown=# SELECT * FROM shipments
booktown-# WHERE Id = currval('shipments_ship_id_seq'):
id | customerjd | Isbn | ship_date
1002 ! 107 | 0394800753 | 2001-09-22 11:23:28-07
(1 row)
Наконец, функция setval () присваивает атрибуту 1 ast_val lie последовательности произвольное число из интервала допустимых значений. Первый аргумент функции содержит имя последовательности, заключенное в апострофы, а второй аргумент содержит целочисленную константу, представляющую новое значение last_value.
Существует два варианта вызова функции setval О. По умолчанию предполагается, что новое значение относится к инициализированной последовательности; это означает, что следующее значение, возвращенное nextval О, уже будет увеличено по отношению к величине, переданной при вызове setval О.
Кроме того, последовательность можно деинициализировать, для чего в необязательном последнем аргументе передается логическая величина false. Последовательность изменяется так, что следующий вызов nextval О вернет то же число, которое было передано при вызове setval () (хотя при следующем вызове nextval () последовательность увеличится).
В листинге 7.32 приведены оба варианта замены текущего значения последовательности shipments_ship_id_seq с последующими вызовами nextval О, демонстрирующими полученный результат.
Изменение текущего значения последовательности
Листинг 7.32. Изменение текущего значения последовательности
booktown=# SELECT setval('shipments_ship_1d_seq'. 1010);
setval
1010
(1 row)
booktown=# SELECT nextval('shipments_ship_id_seq');
nextval
1011
(1row)
booktown=# SELECT setvalСshipments_ship_id_seq', 1010. false);
setval
1010
(1 row)
booktown=# SELECT nextval ('shipnients_ship_id_seq');
nextval
1010
(1 row)
ВНИМАНИЕ
Последовательности обычно применяются для обеспечения уникальности значений полей. Прежде чем изменять атрибут 1ast_value, убедитесь в том, что вы хорошо понимаете все возможные последствия.
Удаление последовательности
Листинг 7.33. Удаление последовательности
booktown=# DROP SEQUENCE shipments_ship_id_seq;
DROP
Прежде чем уничтожать последовательность, убедитесь в том, что она не используется другой таблицей, функцией или другим объектом базы данных. Если забыть об этой проверке, это нарушит работу других операций, зависящих от данной последовательности. Следующий запрос возвращает имена всех отношений, в которых заданная последовательность используется при вычислении значений по умолчанию:
SELECT p.relname. a.adsrc FROM pg_class p
JOIN pg_attrdef a ON (p.relfilenode = a.adrelid)
WHERE a.adsrc - '"последовательность"';
В листинге 7.34 с помощью этого запроса выполняется поиск имен таблиц, у которых последовательность shipments_ship_id_seq используется для вычислений значений по умолчанию.
Проверка зависимостей
Листинг 7.34. Проверка зависимостей
Dooktown=# SELECT p.relname. a.adsrc FROM pg_class p JOIN pg_attrdef a
booktown-# ON (p.relfilenode = a.adrelid)
booktown-# WHERE a.adsrc - '"shipments_ship_id_seq"';
relname | adsrc
shipments | nextvaK'"sh1pments_ship_id_seq"'::text)
(1 row)
Создание триггера check_shipment
Листинг 7.35. Создание триггера check_shipment
booktown=# CREATE TRIGGER check_shipment
booktown-# BEFORE INSERT OR UPDATE
booktown-# ON shipments FOR EACH ROW
booktown-# EXECUTE PROCEDURE check_shipment_addition();
CREATE
Триггер check_shipment настроен на выполнение функции check_shipment_addition() для команд INSERT и UPDATE, поэтому он достаточно надежно обеспечивает логическую целостность данных в полях customerjd и i sbn. Ключевое слово ROW гарантирует, что каждая добавляемая или модифицируемая запись будет обработана функцией проверки check_argument_addition().
Функция check_shipment_addition() вызывается без аргументов, поскольку для проверки записей в ней используются внутренние переменные PL/pgSQL. Реализация функции check_shipments_addition() на языке PL/pgSQL приведена в главе 11.
Удаление триггера
Листинг 7.36. Удаление триггера
booktown=# DROP TRIGGER check_shipment ON shipments:
DROP
Сообщение DROP означает, что триггер успешно удален. Обратите внимание: при удалении указывается не только имя удаляемого триггера, но и имя таблицы.
Если вы не помните, в какой таблице был установлен удаляемый триггер, необходимую информацию можно получить из системных таблиц PostgreSQL. Например, можно провести объединение полей tgrelid системной таблицы pg_trigger и поля rel f i I enode системной таблицы pg_cl ass и сравнить имя триггера с полем tgname. Запрос, приведенный в листинге 7.37, возвращает имя отношения (rel name), связанного с триггером check_shipment.
Получение имени таблицы связанной с триггером
Листинг 7.37. Получение имени таблицы, связанной с триггером
booktown=# SELECT relname FROM pg_class
booktown-# INNER JOIN pg_trigger
booktown-# ON (tgrelid = relfilenode)
booktown-# WHERE tgname = 'check_shipment': .
relname
shipments
(1 row)
ВНИМАНИЕ
При удалении функции, вызываемой по срабатыванию триггера, триггер перестает работать, причем повторное определение функции с тем же именем не исправит проблему. После повторного создания функции триггер также приходится создавать заново.
Создание транзакции
Листинг 7.38. Создание транзакции
bOOktown=# BEGIN;
BEGIN
С точки зрения пользователя, вносящего изменения в базу данных, все команды SQL после команды BEGIN выполняются немедленно. Но как упоминалось выше, для других пользователей эти изменения остаются невидимыми вплоть до момента фиксации транзакционного блока.
Транзакционный блок завершается командой SQL COMMIT, за которой также могут следовать необязательные ключевые слова WORK или TRANSACTION. В листинге 7.39 команда SQL COMMIT синхронизирует состояние базы данных с результатами команды UPDATE.
Фиксация транзакции
Листинг 7.39. Фиксация транзакции
booktown-# BEGIN; BEGIN
booktown=# UPDATE subjects SET location = NULL
booktown-f WHERE id = 12;
UPDATE 1
booktown=# SELECT location FROM subjects WHERE id - 12:
location
(1 row)
booktown=# COMMIT;
COMMIT
Как видно из листинга, хотя результаты команды UPDATE немедленно отражаются на выборке, выполняемой командой SELECT, другие пользователи, подключенные к той же базе данных, ничего не будут знать о них вплоть до выполнения команды COMMIT.
Транзакции откатываются командой SQL ROLLBACK, за которой также могут следовать необязательные ключевые слова WORK или TRANSACTION.
В листинге 7.40 мы создаем транзакцию, вносим изменения в таблицу subjects и убеждаемся в их присутствии. Затем транзакция откатывается, и таблица возвращается к состоянию, в котором она находилась до начала транзакции.
Выбор типа индекса
Листинг 7.4. Выбор типа индекса
booktown=# CREATE TABLE polygons (shape polygon):
CREATE
booktown=f CREATE INDEX spadaljdx ON polygons USING RTREE (shape);
CREATE
ВНИМАНИЕ
Если у вас нет твердой, обоснованной уверенности в том, что для конкретной ситуации лучше подойдет другой тип индекса, мы рекомендуем использовать стандартный тип BTREE.
Откат транзакции
Листинг 7.40. Откат транзакции
booktown=# и
BEGIN
booktown=# SELECT * FROM subjects WHERE id = 12;
id | subject | location
12 | Religion | (1 row)
booktown=# UPDATE subjects SET location = 'Sunset Dr'
booktown-# WHERE id = 12;
UPDATE 1
booktown=# SELECT * FROM subjects WHERE id = 12;
id | subject | location
12 | Religion | Sunset Dr
(1 row)
booktown=# ROLLBACK;
ROLLBACK
booktown=# SELECT * FROM subjects WHERE id = 12;
id | subject I location
12 ] Religion |
(1 row)
PostgreSQL предельно строго относится к ошибкам, возникающим при выполнении команд в транзакциях. Даже простейшие ошибки, вроде приведенной в листинге 7.41, переводят транзакцию в аварийное состояние. В этом состоянии запрещается выполнение любых команд, кроме команд завершения транзакции
(COMMIT или ROLLBACK).
Выход из аварийного состояния
Листинг 7.41. Выход из аварийного состояния
booktown=# BEGIN:
BEGIN
booktown=# SELECT * FROM;
ERROR: parser: parse error at or near ";"
booktown=# SELECT * FROM books;
NOTICE: current transaction is aborted, queries ignored until end of transaction
*ABORT STATE*
booktown=# COMMIT;
Объявление курсора
Листинг 7.42. Объявление курсора
booktown=# BEGIN;
BEGIN
booktown=# DECLARE all_books CURSOR
booktown-# FOR SELECT * FROM books;
SELECT
Сообщение SELECT в конце листинга 7.42 говорит о том, что команда была выполнена успешно, а записи, полученные в результате запроса, стали доступными для курсора a! l_books.
Выборка записей из курсора
Листинг 7.43. Выборка записей из курсора
booktown=# FETCH 4 FROM all_books;
Id | title | authored | suojectjd
7808 | The Shining | 4156 | 9
4513 | Dune 1 1866 | 15
4267 I 2001: A Space Odyssey | 2001 | 15
1608 I The Cat in the Hat j 1809 2
(4 rows)
booktown=# FETCH NEXT FROM all_books;
id | title | authorjd | subjectjd
1590 Bartholomew and the Oobleck 1809 2
(1 row)
booktown=# FETCH PRIOR FROM all_books:
id | title | authorjd subjectjd
1608 | The Cat in the Hat | 1809 | 2
(1 row)
Перемещение текущей позиции курсора
Листинг 7.44. Перемещение текущей позиции курсора
booktown=# MOVE FORWARD 10
booktown-# IN all_books;
MOVE
Закрытие курсора
Листинг 7.45. Закрытие курсора
booktown=# CLOSE al1_books;
CLOSE
booktown=# COMMIT:
COMMIT
Создание функции SQL
Листинг 7.46. Создание функции SQL
booktown=# CREATE FUNCTION isbn_to_title(text) RETURNS text
booktown-l AS 'SELECT title FROM books
booktown'f JOIN editions AS e (isbn. id)
booktown'# USING (id)
booktown'# WHERE isbn = $1'
booktown-# LANGUAGE 'SQL';
CREATE
Позиционный параметр $1 при выборке заменяется значением первого аргумента в списке, переданном при вызове функции 1sbn_to_title. Позиционный параметр не заключается в отдельные апострофы, поскольку апострофы являются частью переданного аргумента. Остальные составляющие определения функции являются либо идентификаторами, либо стандартными ключевыми словами SQL
Сообщение CREATE означает, что создание функции прошло успешно. В листинге 7.47 функция i sbn_to_ti tl e вызывается с одним текстовым аргументом 0929605942. Функция возвращает название книги, связанное с этим кодом ISBN. При этом используется код SQL, содержащийся в листинге 7.46.
Использование функции SQL
Листинг 7.47. Использование функции SQL
booktown=# SELECT isbn_to_title('0929605942');
isbn to title
The Tell-Tale Heart
(1 row)
Созданная функция доступна для всех пользователей, обладающих соответствующими правами. Например, для выполнения функции 1sbn_to_title необходим доступ для чтения к таблицам editions и books (права пользователей описаны в главе 10).
Функции на языке С
Листинг 7.48. Функции на языке С
/* 1s_zero.c
* Простейшие проверочные функции */
int is_zero(int);
int is_zero_two(int. int):
int is_zero(int incoming) {
/* Вернуть true, если аргумент равен 0. */
if (incoming == 0) return 1;
else return 0: }
int is_zero_two(int left, int right) {
/* Вернуть true, если хотя бы один из аргументов равен 0. */
if (left —0 || right == 0) return 1:
else return 0; }
ВНИМАНИЕ
В этот простейший пример не были включены заголовочные файлы PostgreSQL. В данном случае они не нужны из-за очевидного соответствия между типами данных С и SQL. Более реальные примеры с использованием внутреннего интерфейса API PostgreSQL и структур данных находятся во вложенном каталоге contrib исходного каталога PostgreSQL.
В листинге 7.49 файл is_zero.c компилируется с ключом -shared, а полученный общий модуль создается в файле is_zero.so. Путь к файлу передается в определении функции в команде CREATE FUNCTION; атрибут LANGUAGE сообщает, что функция написана на языке С.
Создание функции на языке С
Листинг 7.49. Создание функции на языке С
[jworsley@cmd ~]$ gcc -shared is_zero.c -о is_zero.so
[jworsley@cmd -]$ psql -U manager booktown
Welcome to psql. the PostgreSQL interactive terminal.
Type: \copyright for distribution terms
\h for help with SQL commands
\? for help on internal slash commands
\g or terminate with semicolon to execute query
\q to quit
booktown-* CREATE FUNCTION is_zero(int4) RETURNS Boolean
booktown-l AS '/home/jworsley/is_zero.so' LANGUAGE 'C';
CREATE
Команда CREATE FUNCTION в листинге 7.49 создает функцию с именем is_zero(), которая получает один аргумент типа int4 и возвращает значение типа boolean. В объявление включена ссылка на функцию С с именем i s_zero( i nt), реализованную в объектном модуле /home/jworsley/is_zero.so (поскольку в языке С нет типа boo! ean, PostgreSQL приходится преобразовывать целочисленное значение, возвращаемое функцией, к логическому типу). При этом число 0 преобразуется в fal se, a 1 — в true.
По умолчанию PostgreSQL ищет в общем модуле функцию с тем же именем, с которым она создается в PostgreSQL. Такой способ подходит для функции i s_zero(i nteger), имя которой соответствует откомпилированному символическому имени функции is_zero(int) в файле is_zero.so. Для предотвращения конфликтов имен вторая функция в общем объектном модуле определяется с сигнатурой is_zero_two(int.int). Чтобы ассоциировать ее с перегруженной функцией PostgreSQL, получающей два аргумента вместо одного, имя функции С в виде строковой константы передастся после пути к файлу общего модуля.
Имя указывается без круглых скобок и без перечисления аргументов, а от пути к файлу оно отделяется запятой:
CREATE FUNCTION имя ( [ тип_аргумента [. ...] ] )
RETURNS тип_возвращаемого_значения
AS 'определение'. 'имя_в_объектном_файле'
LANGUAGE 'С' [ WITH ( атрибут [. ...] ) ]
В листинге 7.50 подгружается тот же общий модуль, но на этот раз перегруженная функция PostgreSQL ассоциируется с функций С is_zero_two.
Построение функционального индекса
Листинг 7.5. Построение функционального индекса
booktown=# CREATE INDEX upperjtitlejdx ON books
booktown-f (upper(title));
CREATE
booktown=# SELECT title FROM books WHERE upper(title) = 'DUNE';
title
Dune
(1 row)
Перегрузка функции С
Листинг 7.50. Перегрузка функции С
booktown=# CREATE FUNCTION is_zero(int4. int4) RETURNS Boolean
booktown-# AS '/home/jworsley/is_zero.so'. 'is_zero_two'
booktown-* LANGUAGE 'C':
CREATE
Функции С, как и функции SQL, могут вызываться любым пользователем. Функции С могут вносить прямые изменения в файловую систему (если позволяют права) и производить операции системного уровня, поэтому к их проектированию следует подойти особенно тщательно, чтобы избежать потенциальных злоупотреблений. В листинге 7.51 приведены примеры нескольких вызовов функции i s_zero, определенной в листинге 7.49, и ее перегруженной версии из листинга 7.51.
Использование функций С
Листинг 7.51. Использование функций С
booktown=# SELECT is_zero(0) AS zero. is_zero(l) AS one,
booktown-# 1s_zero(6. 0) AS one_zero, is_zero(11.12) AS neither:
zero | one | one_zero | neither
t [ f | t | f
(1 row)
Удаление функции
Листинг 7.52. Удаление функции
booktown=# DROP FUNCTION isbn_to_title(text);
DROP
Сообщение сервера DROP означает, что функция была успешно удалена. Команда DROP FUNCTION, как и большинство команд DROP, необратима, поэтому перед ее выполнением убедитесь в том, что функцию действительно требуется удалить.
Создание пользовательского оператора
Листинг 7.53. Создание пользовательского оператора
booktown=# CREATE OPERATOR !# (PROCEDURE = is_zero,
booktown(# LEFTARG = integer);
CREATE
Сообщение CREATE означает, что создание оператора прошло успешно. Новый оператор становится доступным для любого пользователя, подключенного к базе данных (по аналогии с функциями). Оператор принадлежит пользователю, создавшему его, и поэтому не может быть удален другим пользователем, не обладающим правами суперпользователя. В листинге 7.54 новый оператор !# возвращает из таблицы stock список книг, отсутствующих на складе.
Применение пользовательского оператора
Листинг 7.54. Применение пользовательского оператора
booktown=# SELECT * FROM stock WHERE stock !#;
isbn | cost | retail | stock
0394900014 | 23.00 | 23.95 | 0
0451198492 | 36.00 | 46.95 | 0
0451457994 | 17.00 j 22.95 | 0
(3 rows)
Перегрузка пользовательского оператора
Листинг 7.55. Перегрузка пользовательского оператора
booktown=# CREATE OPERATOR !# (PROCEDURE = is_zero.
booktown(# RIGHTARG = integer);
CREATE
booktown=# CREATE OPERATOR !# (PROCEDURE = is_zero,
booktown(# LEFTARG = integer,
booktown(# RIGHTARG = integer);
CREATE
В листинге 7.55 оператор !# перегружается с тем же именем функции is_zero(), поскольку сама функция была перегружена в листинге 7.50 (см. пункт «Создание функций на языке С» в подразделе «Создание новых функций» данного раздела). Наличие двух версий функции is_zero() (с одним и с двумя аргументами) позволяет перегрузить оператор !# в двух вариантах, с одним операндом (левым или правым) и с двумя операндами.
Лексический анализатор PostgreSQL правильно интерпретирует все перегруженные операторы в командах SQL. В листинге 7.56 продемонстрированы три варианта использования оператора !# с разными операндами. Все три варианта допустимы, так как оператор был перегружен в листинге 7.55.
Использование перегруженного оператора
Листинг 7.56. Использование перегруженного оператора
booktownHf SELECT isbn, stock FROM stock booktown-# WHERE stock !#
booktown-# AND !# stock
booktown-# AND stock !# stock;
isbn | stock
0394900014 0
0451198492 | 0
0451457994 | 0
(3 rows)
Удаление оператора
Листинг 7.57. Удаление оператора
booktown=# DROP OPERATOR !# (integer, integer);
DROP
Команда в листинге 7.58 выглядит почти так же, но она удаляет перегруженную версию с правым операндом.
Удаление перегруженного оператора
Листинг 7.58. Удаление перегруженного оператора
booktown=# DROP OPERATOR !# (NONE, integer);
DROP
Удаление индекса
Листинг 7.6. Удаление индекса
booktown=# DROP INDEX upper_title_idx:
DROP
Создание таблицы с ограничениями полей
Листинг 7.7. Создание таблицы с ограничениями полей
booktown=# CREATE TABLE employees
booktown-f (id integer PRIMARY KEY CHECK (id >
100).
booktown(# lastjiame text NOT NULL.
booktown(# first_name text);
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'employeesjjkey'
for table 'employees'
CREATE
В листинге 7.7 создается поле id типа integer, для которого устанавливаются ограничения PRIMARY KEY и CHECK. Ограничение PRIMARY KEY также подразумевает ограничения NOT NULL и UNIQUE и приводит к автоматическому созданию индекса empl oyees_pkey для ограничиваемого поля. Ограничение CHECK гарантирует, что значение поля id всегда больше 100. Это означает, что любые попытки вставки или обновления в таблице empl oyees записей, у которых поле id меньше либо равно 100, завершаются неудачей.
Таблица employees, созданная в листинге 7.7, также содержит текстовое поле 1 astjiame, для которого установлено ограничение NOT NULL. Это более простое ограничение запрещает появление в таблице записей, у которых поле lastjiame содержит NULL. Иначе говоря, это поле обязательно для заполнения.
Примечание 1
Примечание 1
Условия в секциях CHECK должны оперировать со значениями сравнимых типов данных.
Использование ограничений таблицы
Листинг 7.8. Использование ограничений таблицы
booktown=# CREATE TABLE editions
booktown-# (isbn text,
booktown(# bookjid integer,
booktown(# edition integer,
booktown(# publisherjd integer,
booktownCl publication date.
booktown(# type char,
booktown(# CONSTRAINT pkey PRIMARY KEY (isbn),
booktown(# CONSTRAINT integrity CHECK (bookjd IS NOT NULL
booktown(# AND edition IS NOT NULL).
booktown(# CONSTRAINT book_exists FOREIGN KEY (bookjd)
booktown(# REFERENCES books (id)
booktown(# ON DELETE CASCADE
booktown(# ON UPDATE CASCADE);
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pkey1 for table
'editions'
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
CREATE
Первое ограничение, pkey, относится к типу PRIMARY KEY и устанавливается для таблицы по полю isbn. Оно практически не отличается от ограничения PRIMARY KEY для поля, поскольку список в данном примере состоит всего из одного поля.
Ограничение i ntegri ty гарантирует, что поля book i d и edi ti on не содержат псевдозначения NULL.
Наконец, ограничение book_exists при помощи конструкций FOREIGN KEY и REFERENCES гарантирует, что значение поля book_id встречается в поле id таблицы books. Более того, поскольку в секциях ON DELETE и ON ACTION встречается ключевое слово CASCADE, любые модификации поля ids таблице books приведут к каскадным изменениям записей в таблице editions, а при удалении записей из таблицы books будут удалены соответствующие записи таблицы editions.
Для этих ограничений в базе данных автоматически строится индекс editions_pkey по полю isbn, а также создается триггер. Индекс обеспечивает выполнение ограничения PRIMARY KEY, а триггер относится к ограничению FOREIGN KEY.
Добавление ограничений в существующую таблицу
Листинг 7.9. Добавление ограничений в существующую таблицу
booktown=# ALTER TABLE books
booktown-# ADD CONSTRAINT legal_subjects
booktown-# FOREIGN KEY (subjectjd)
booktown-# REFERENCES subjects (id);
NOTICE: ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for
FOREIGN KEY check(s)
CREATE
Массивы
Массивы
Как упоминалось в главе 3, поля данных PostgreSQL вместо отдельных величин могут содержать конструкции, называемые массивами. Массив сам по себе не является самостоятельным типом данных, а лишь расширяет любой другой тип данных PostgreSQL.
Модификация производных таблиц
Модификация производных таблиц
Как упоминалось в предыдущем разделе, процесс включения данных в базовые и производные таблицы весьма прямолинеен. Вставка в производную таблицу приводит к кажущемуся появлению данных в базовой таблице, хотя сами данные по-прежнему находятся в производной таблице. Вставка данных в базовую таблицу никак не отражается на производной таблице.
Процесс модификации данных в производной таблице достаточно прост и очевиден — изменяется только содержимое производной таблицы, а все данные из базовой таблицы остаются без изменений. Как говорилось выше, данные не являются общими в обычном смысле слова, а лишь видны в других таблицах. Выборка из базовой таблицы без ключевого слова ONLY выведет как записи базовой таблицы, так и модифицированные записи производной таблицы.
С модификацией записей в базовых таблицах дело обстоит сложнее. Команды UPDATE и DELETE по умолчанию работают не только с записями базовой таблицы, но и с записями всех производных таблиц, подходящих по заданному критерию. В листинге 7.14 выполняется команда UPDATE для таблицы authors. Как видно из листинга, команда также изменяет записи таблицы di stinguished_authors.
Наследование
Наследование
В PostgreSQL поддерживается механизм создания объектно-реляционных связей, называемый наследованием. Таблица может наследовать некоторые атрибуты своих полей от одной или нескольких других таблиц, что приводит к созданию отношений типа «предок—потомок». В результате производные таблицы («потомки») обладают теми же полями и ограничениями, что и их базовые таблицы («предки»), а также дополняются собственными полями.
При составлении запроса к базовой таблице можно потребовать, чтобы запрос произвел выборку только из самой таблицы или же просмотрел как таблицу, так и ее производные таблицы. С другой стороны, в результаты запроса к производной таблице никогда не включаются записи из базовой таблицы.
Нетривиальное использование таблиц
Нетривиальное использование таблиц
В PostgreSQL предусмотрено несколько вариантов ограничения данных, участвующих в операциях вставки и обновления. Один из них заключается в установке ограничений для таблиц и полей.
Кроме того, в PostgreSQL поддерживается механизм наследования, характерный для объектно-реляционных СУБД. Наследование позволяет установить между таблицами связи типа «предок—потомок» и создать иерархию полей.
В этом разделе будут рассмотрены обе темы. Кроме того, речь пойдет о создании и практическом применении производных таблиц.
Нетривиальные возможности
Нетривиальные возможности
В данной главе рассматриваются нетривиальные возможности PostgreSQL, в том числе оптимизация доступа к таблицам с использованием индексов, наследование и установка ограничений для таблиц, практическое применение массивов в значениях полей, работа с транзакциями и курсорами. Все перечисленные возможности выгодно отличают PostgreSQL от других реляционных СУБД.
Кроме того, в этой главе описаны такие концепции из области программирования, как триггеры и последовательности. Наконец, для программистов, занимающихся разработкой специализированных процедур для работы с базой данных, описано, как расширить возможности PostgreSQL путем определения пользовательских функций и операторов.
Объявление курсора
Объявление курсора
Команда SQL DECLARE создает курсор и выполняет его. Этот процесс также называется открытием курсора. Курсор может быть объявлен только в существующем транзакционном блоке, поэтому перед объявлением курсора должна быть выполнена команда BEGIN. Синтаксис команды DECLARE:
DECLARE курсор [ BINARY ] [ INSENSITIVE ] [ SCROLL ]
CURSOR FOR запрос
[ FOR { READ ONLY | UPDATE [ OF none [. ...]]}]
- DECLARE курсор. Имя создаваемого курсора.
- [ BINARY ]. Ключевое слово BINARY означает, что выходные данные должны возвращаться в двоичном формате вместо стандартного ASCII-кода. Иногда переключение на двоичный формат повышает эффективность курсора, но это относится лишь к пользовательским приложениям, поскольку стандартные клиенты (такие, как psql) работают только с текстовым выводом.
- [ INSENSITIVE ] [ SCROLL ]. Ключевые слова INSENSITIVE и SCROLL существуют для совместимости со стандартом SQL, но они описывают поведение PostgreSQL по умолчанию, поэтому их присутствие не обязательно. Ключевое слово SQL INSENSITIVE обеспечивает независимость данных, возвращенных курсором, от других курсоров или подключении. Поскольку PostgreSQL требует, чтобы курсоры определялись в транзакционных блоках, это требование заведомо выполняется. Ключевое слово SQL SCROLL указывает, что курсор поддерживает одновременную выборку нескольких записей. Этот режим поддерживается в PostgreSQL по умолчанию, даже если ключевое слово SCROLL не указано.
- CURSOR FOR запрос. Запрос, после выполнения которого итоговый набор становится доступным через курсор.
- FOR { READ ONLY | UPDATE [ OF поле [. ...] ] }. В PostgreSQL 7.1.x поддерживаются курсоры, доступные только для чтения (READ ONLY), поэтому секция FOR оказывается лишней.
Ограничения полей
Ограничения полей
При выполнении команды \h CREATE TABLE клиент psql выводит несколько подробных синтаксических диаграмм для ограничений, которые могут устанавливаться для таблиц. Синтаксис ограничения поля выглядит так:
[ CONSTRAINT ограничение ]
{ NOT NULL UNIQUE | PRIMARY KEY | DEFAULT значение | CHECK ( условие ) | REFERENCES таблица [ ( поле ) ]
[ MATCH FULL | MATCH PARTIAL ]
[ ON DELETE операция ]
[ ON UPDATE операция ]
[ DEFERRABLE | NOT DEFERRABLE ]
[ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] }
Определение следует в команде CREATE TABLE сразу же за типом ограничиваемого поля и предшествует запятой, отделяющей его от следующего поля. Ограничения могут устанавливаться для любого количества полей, а ключевое слово CONSTRAINT и идентификатор ограничение не обязательны.
Существует шесть типов ограничений полей, задаваемых при помощи специальных ключевых слов. Некоторые из них косвенно устанавливаются при создании ограничений другого типа. Типы ограничений полей перечислены ниже.
- NOT NULL. Поле не может содержать псевдозначение NULL. Ограничение NOT NULL эквивалентно ограничению CHECK (поле NOT NULL).
- UNIQUE. Поле не может содержать повторяющиеся значения. Следует учитывать, что ограничение UNIQUE допускает многократное вхождение псевдозначений NULL, поскольку формально NULL не совпадает ни с каким другим значением.
- PRIMARY KEY. Автоматически устанавливает ограничения UNIQUE и NOT NULL, а для заданного поля создается индекс. В таблице может устанавливаться только одно ограничение первичного ключа.
- DEFAULT значение. Пропущенные значения поля заменяются заданной величиной. Значение по умолчанию должно относиться к типу данных, соответствующему типу поля. В PostgreSQL 7.1.x значение по умолчанию не может задаваться при помощи подзапроса.
- CHECK условие. Команда INSERT или UPDATE для записи завершается успешно лишь при выполнении заданного условия (выражения, возвращающего логический результат). При установке ограничения поля в секции CHECK может использоваться только поле, для которого устанавливается ограничение.
- REFERENCES. Это ограничение состоит из нескольких секций, которые перечислены ниже.
- REFERENCES таблица [ ( поле ) ]. Входные значения ограничиваемого поля сравниваются со значениями другого поля в заданной таблице. Если совпадения отсутствуют, команда INSERT или UPDATE завершается неудачей. Если параметр поле не указан, проверка выполняется по первичному ключу. Ограничение REFERENCES похоже на ограничение таблицы FOREIGN KEY, описанное в следующем пункте этого подраздела. Действительно, между этими ограничениями есть много общего. Пример таблицы, созданной с ограничением FOREIGN KEY, приведен в листинге 7.8.
- MATCH FULL | MATCH PARTIAL. Секция MATCH указывает, разрешается ли смешивание значений NULL и обычных значений при вставке в таблицу, у которой внешний ключ ссылается на несколько полей. Таким образом, на практике секция MATCH приносит пользу лишь в ограничениях таблиц, хотя формально она может использоваться и при ограничении полей. Конструкция MATCH FULL запрещает вставку данных, у которых часть полей внешнего ключа содержит псевдозначение NULL (кроме случая, когда NULL содержится во всех полях). В PostgreSQLV.l.x конструкция MATCH PARTIAL не поддерживается. Если секция MATCH отсутствует, считается, что поля с псевдозначениями NULL удовлетворяют ограничению. Также будет уместно напомнить, что ограничения полей относятся лишь к одному полю, поэтому секция MATCH используется лишь в ограничениях таблиц.
- ON DELETE операция. При выполнении команды DELETE для заданной таблицы с ограничиваемым полем выполняется одна из следующих операций: N0 ACTION (если удаление приводит к нарушению целостности ссылок, происходит ошибка; используется по умолчанию, если операция не указана), RESTRICT (аналогично NO ACTION), CASCADE (удаление всех записей, содержащих ссылки на удаляемую запись), SET NULL (поля, содержащие ссылки на удаляемую запись, заменяются псевдозначениями NULL), SET DEFAULT (полям, содержащим ссылки на удаляемую запись, присваивается значение по умолчанию).
- ON UPDATE операция. При выполнении команды UPDATE для заданной таблицы выполняется одна из операций, описанных выше. По умолчанию используется значение NO ACTION. Если выбрана операция CASCADE, все записи, содержащие ссылки на обновляемую запись, обновляются новым значением (вместо удаления, как в случае с ON DELETE CASCADE).
- DEFERRABLE | NOT DEFERRABLE. Значение DEFERRABLE позволяет отложить выполнение ограничения до конца транзакции (вместо немедленного выполнения после завершения команды). Значение NOT DEFERRABLE означает, что ограничение всегда проверяется сразу же после завершения очередной команды. В этом случае пользователь не может отложить проверку ограничения до конца транзакции. По умолчанию выбирается именно этот вариант.
- INITIALLY DEFERRED | INITIALLY IMMEDIATE. Секция INITIALLY задается только для ограничений, определенных с ключевым словом DEFERRED. Значение INITIALLY DEFERRED откладывает проверку ограничения до конца транзакции, а при установке значения INITIALLY IMMEDIATE проверка производится после каждой команды. При отсутствии секции INITIALLY по умолчанию используется значение INITIALLY IMMEDIATE.
Ограничения таблиц
Ограничения таблиц
В ограничениях таблиц, в отличие от ограничений полей, могут участвовать сразу несколько полей таблицы. Синтаксис ограничения таблицы:
[ CONSTRAINT ограничение ] { UNIQUE ( поле [. ...] ) | PRIMARY KEY ( поле [. ...] ) | CHECK ( условие ) ] FOREIGN KEY ( поле [. ... ] )
REFERENCES таблица [ ( поле [....])]
[ MATCH FULL | MATCH PARTIAL ]
[ ON DELETE операция ]
[ ON UPDATE операция ]
[ DEFERRABLE | NOT DEFERRABLE ]
[ INITIALLY DEFERRED INITIALLY IMMEDIATE ]
Секция CONSTRAINT ограничение определяет необязательное имя. Ограничениям рекомендуется присваивать содержательные имена вместо автоматически сгенерированных имен, не несущих никакой полезной информации. В будущем имя также может пригодиться и для удаления ограничения (например, в секции DROP CONSTRAINT команды ALTER TABLE). Другие секции относятся к четырем разновидностям ограничений таблиц.
- PRIMARY KEY ( поле [. ...] ). Ограничение таблицы PRIMARY KEY имеет много общего с аналогичным ограничением поля. В ограничении таблицы PRIMARY KEY могут перечисляться несколько полей, разделенных запятыми. Для перечисленных полей автоматически строится индекс. Как и в случае с ограничением поля, комбинация значений всех полей должна быть уникальной и не может содержать NULL.
- UNIQUE ( поле [. ...] ). Ограничение означает, что комбинация значений полей, перечисленных за ключевым словом UNIQUE, принимает только уникальные значения. Допускается многократное вхождение псевдозначения NULL, поскольку оно формально не совпадает ни с одним значением.
- CHECK ( условие ). Команда INSERT или UPDATE для записи завершается успешно лишь при выполнении заданного условия (выражения, возвращающего логический результат). Используется по аналогии с ограничениями полей, но в секции CHECK может содержать ссылки на несколько полей.
- FOREIGN KEY ( поле [. ... ] ) REFERENCES таблица [ ( поле [. ... ] ) ]. В качестве прототипа для секции REFERENCES можно перечислить несколько полей. Синтаксис части, следующей за секцией FOREIGN KEY, идентичен синтаксису ограничения REFERENCES для полей.
Ограничения в таблицах
Ограничения в таблицах
Ограничение (constraint) представляет собой особый атрибут таблицы, который устанавливает критерии допустимости для содержимого ее полей. Соблюдение этих правил помогает предотвратить заполнение базы ошибочными или неподходящими данными.
Ограничения задаются в секции CONSTRAINT при создании таблицы командой CREATE TABLE. Они делятся на два типа — ограничения полей и ограничения таблиц.
Ограничения полей всегда относятся только к одному полю, тогда как ограничения таблиц могут устанавливаться как для одного, так и для нескольких полей. В команде CREATE TABLE ограничения полей задаются сразу же после определения поля, тогда как ограничение таблицы устанавливается в специальном блоке, отделенном запятой от всех определений полей. Поля, на которые распространяется ограничение таблицы, задаются самим определением, а не его расположением в команде.
Ниже описаны различные правила, устанавливаемые при помощи ограничений.
Операции с последовательностями
Операции с последовательностями
Выборка атрибутов последовательности требуется относительно редко. Как правило, все операции с последовательностями выполняются при помощи трех специальных функций PostgreSQL.
- nextval ('последовательность'). Увеличивает текущее значение заданной последовательности и возвращает новое значение в виде величины типа 1 nteger.
- currval ('последовательность'). Возвращает значение, полученное при последнем вызове nextval О. Значение ассоциируется с определенным сеансом PostgreSQL, поэтому если функция nextval () еще не вызывалась для заданного подключения в текущем сеансе, функция не сможет вернуть значение.
- setval ('последовательность'. п). Присваивает число п текущему значению заданной последовательности. Следующий вызов nextval О возвращает значение п+приращение, где приращение — изменение текущего значения последовательности при каждой итерации.
- setval ('последовательность'. п. Ь). Также присваивает число п текущему значению заданной последовательности. Если параметр b (тип boo! ean) равен f al se, то следующий вызов nextval () вернет значение п, а если параметр равен true, то будет возвращено значение п+приращение, как при вызове функции setval О без дополнительного аргумента.
В листинге 7.30 выводится пара очередных значений последовательности с именем shipments_ship_id_seq.
Определение количества элементов
Определение количества элементов
Чтобы узнать количество значении, хранящихся в массиве, следует воспользоваться функцией array_dims(). В качестве параметра функции передается идентификатор — имя поля-массива, для которого вызывается функция. Результат возвращается в виде строки, содержащей описание массива в синтаксисе среза. В листинге 7.25 приведен пример вызова функции array_dims() для поля books таблицы favorite_books.
Перегрузка операторов
Перегрузка операторов
Операторы, как и функции, поддерживают возможность перегрузки. Иначе говоря, в программе можно создать оператор с таким же именем, как у существующего
оператора, но работающего с другими типами операндов. При этом в программе должна существовать функция, количество и тины аргументов которой соответствуют количеству и типам операндов.
Пример перегрузки оператора !# приведен в листинге 7.55. Первая команда CREATE OPERATOR создает оператор, аналогичный оператору из листинга 7.53. Тем не менее в новой версии оператора вместо LEFTARG указано ключевое слово RIGHTARG, поэтому новый оператор работает с операндом типа integer, находящимся не слева, а справа. Вторая команда создает третью версию оператора !#, работающую с обоими операндами.
Перемещение курсора
Перемещение курсора
Курсор поддерживает информацию о текущей позиции в итоговом наборе команды SELECT. Перемещение курсора к заданной записи выполняется командой MOVE. Синтаксис команды MOVE:
MOVE [ FORWARD | BACKWARD | RELATIVE ]
[ число ALL | NEXT | PRIOR ]
{ IN | FROM } курсор
Как видно из приведенного объявления, синтаксис команды MOVE очень близок к синтаксису команды FETCH. Впрочем, команда MOVE никаких записей не возвращает и лишь перемещает текущую позицию курсора. Смещение задается целочисленной константой или ключевым словом ALL (перемещение в заданном направлении на максимально возможное расстояние), NEXT или PRIOR. В листинге 7.44 текущая позиция курсора перемещается на 10 записей вперед.
Получение информации о триггерах
Получение информации о триггерах
В PostgreSQL триггеры хранятся в системной таблице pg_trigger, что позволяет получить информацию о существующих триггерах на программном уровне. Структуру таблицы pg_trigger иллюстрирует табл. 7.3.
Последовательности
Последовательности
Последовательностью (sequence) в PostgreSQL называется объект базы данных, который фактически представляет собой автоматически увеличивающееся число. В других СУБД последовательности часто называются счетчиками. Последовательности очень часто используются для присваивания уникальных значении идентификаторов в таблицах. Последовательность определяется текущим числовым значением и набором характеристик, определяющих алгоритм автоматического увеличения (или уменьшения) используемых данных.
Наряду с текущим значением в определение последовательности также включается минимальное значение, максимальное значение и приращение. Обычно приращение равно 1, но оно также может быть любым целым числом.
На практике последовательности не рассчитаны на прямой доступ из программы. Работа с ними осуществляется через специальные функции PostgreSQL, предназначенные для увеличения, присваивания или получения текущего значения последовательности.
Просмотр последовательностей в базе данных
Просмотр последовательностей в базе данных
Команда \d клиента psql показывает, к какому типу относится тот или иной объект базы данных — последовательность, таблица, представление или индекс. Для получения более конкретной информации можно воспользоваться командой \ds, выводящей список всех последовательностей в текущей базе данных. Пример:
booktown=# \ds
List of relations Name Type | Owner
book_ids | sequence | manager
shipments_ship_id_seq j sequence | manager
subject_ids j sequence | manager
(3 rows)
К последовательности также можно обратиться командой SELECT, как к таблице или представлению (хотя такая возможность используется относительно редко). При составлении запроса к последовательности в списке выборки вместо полей указываются атрибуты последовательности, перечисленные в табл. 7.1.
Расширение PostgreSQL
Расширение PostgreSQL
PostgreSQL не ограничивает пользователя встроенными функциями и операторами, позволяя ему создавать собственные расширения. Если вам приходится часто выполнять некоторую стандартную последовательность команд SQL или программных операций, пользовательские функции помогут решить эту задачу более надежно и эффективно. Также в PostgreSQL предусмотрена возможность определения операторов для вызова пользовательских (или встроенных) функций, что делает команды SQL понятнее и эффективнее.
Функции и операторы тоже существуют как объекты базы данных и поэтому связываются с конкретной базой. Например, функция, созданная при подключении к базе данных booktown, доступна только для пользователей, также подключившихся к этой базе.
Если некоторые общие функции или операторы должны использоваться в разных базах данных, создайте их в базе данных template 1. В этом случае объекты функций и операторов будут автоматически копироваться из шаблона template 1 при создании новой базы данных.
В следующих подразделах рассматриваются операции создания, использования и удаления нестандартных функций и операторов.
Создание функций на языке С
Создание функций на языке С
СУБД PostgreSQL, написанная на языке С, может динамически подгружать откомпилированный код С без перекомпиляции пакета. Использование команды
CREATE FUNCTION для компоновки с функциями С разрешено только суперпользователям, поскольку эти функции могут содержать системные вызовы, представляющие потенциальную угрозу для безопасности системы.
Документирование всего интерфейса API системы PostgreSQL выходит за рамки книги. Впрочем, опытный программист сможет очень легко написать, откомпилировать и скомпоновать простейшие функции С с использованием загружаемых общих модулей.
У компилятора gcc (GNU С Compiler) имеется ключ -shared, предназначенный для создания динамически загружаемых модулей. В простейшем случае загружаемый модуль создается командой следующего вида:
$ gcc -shared input.с -о output.so
Здесь input.с — имя файла, содержащего компилируемый код С, a output.so — файл общего загружаемого модуля.
В листинге 7.48 приведена пара очень простых функций, написанных на языке С. Первая функция, is_zero(int), возвращает true (1), если при вызове ей был передан аргумент 0; в противном случае возвращается false (0). Вторая функция, is_zero_two(int. int), возвращает true, если хотя бы один из переданных аргументов равен нулю.
Создание функций SQL
Создание функций SQL
Из всех разновидностей функций в PostgreSQL проще всего создаются «чистые» функции SQL, поскольку их создание не требует ни знания других языков, ни серьезного опыта программирования. Функция SQL определяется как обычная команда с позиционными параметрами.
Позиционный параметр представляет собой ссылку на один из аргументов, переданных при вызове функции SQL. Он называется позиционным, поскольку в ссылке указывается его позиция в списке переданных аргументов. Позиционный параметр состоит из знака $, за которым следует номер (нумерация начинается с 1). Например, $1 означает первый аргумент в переданном списке.
В листинге 7.46 создается функция i sbn_to_ti tl e, которая возвращает название книги по заданному коду ISBN. Функция получает один аргумент типа text и возвращает результат того же типа.
Создание индекса
Создание индекса
Индексы создаются командой SQL CREATE INDEX. Синтаксис команды:
CREATE [ UNIQUE ] INDEX индекс ON таблица
[ USING тип ] ( поле [ класс ] [. ...] )
Здесь индекс — имя создаваемого индекса, таблица — имя таблицы, для которой строится индекс, а поле — имя индексируемого поля. Необязательный параметр тип позволяет выбрать нужную реализацию индекса, а параметр класс описывает операторный класс, используемый для сортировки входных данных.
ВНИМАНИЕ
В PostgreSQL операторные классы хранятся в поле pg_opclass. Используйте этот параметр лишь в том случае, если вы досконально разбираетесь во всех тонкостях операторных классов PostgreSQL.
Команда может содержать список из нескольких индексируемых полей, разделенных запятыми; в этом случае индекс строится для всех перечисленных полей. Составные индексы используются в PostgreSQL только при выполнении команд SQL, осуществляющих поиск по всем индексированным полям с объединением условий ключевым словом AND. В стандартной установке PostgreSQL составной индекс содержит не более 16 полей и реализуется только в виде В-дерева.
Перед построением индекса следует решить, какие поля чаще всего требуются при поиске. Например, хотя таблица books проиндексирована по полю id (первичный ключ), поле title также часто проверяется в условиях WHERE. Включение вторичного индекса по полю title заметно ускорит работу команд SQL, в которых значение этого поля сравнивается с некоторой величиной.
В листинге 7.1 приведен пример построения индекса и просмотра таблицы books при помощи управляющей команды \d psql. Помимо типов полей команда также выводит имена индексов таблицы.
Создание новых функций
Создание новых функций
Разновидность команды SQL99 CREATE FUNCTION, поддерживаемая в PostgreSQL, не обладает прямой совместимостью со стандартом, но зато обеспечивает широкие возможности для расширения PostgreSQL за счет создания пользовательских функций (за информацией о встроенных операторах и функциях обращайтесь к главе 5).
Синтаксис команды CREATE FUNCTION:
CREATE FUNCTION имя ( [ тип_аргумента [. ...] ] )
RETURNS тип_возвращаемого_значения
AS 'определение'
LANGUAGE 'язык'
[ WITH ( атрибут [. ...] ) ]
- CREATE FUNCTION имя ( [ тпип_аргумента [, ...] ] ). После ключевых слов CREATE FUNCTION указывается имя создаваемой функции, после чего в круглых скобках перечисляются типы аргументов, разделенные запятыми. Если список в круглых скобках пуст, функция вызывается без аргументов (хотя сами круглые скобки обязательно должны присутствовать как в определении функции, так и при ее использовании).
- RETURNS тип_возвращаемого^значения. Тип данных, возвращаемый функцией.
- AS ' определение'. Программное определение функции. В процедурных языках (таких, как PL/pgSQL) оно состоит из кода функции. Для откомпилированных функций С указывается абсолютный системный путь к файлу, содержащему объектный код.
- LANGUAGE 'язык'. Название языка, на котором написана функция. В аргументе может передаваться имя любого процедурного языка (такого, как plpgsql или plperl, если соответствующая поддержка была установлена при компиляции), С или SQL.
- [ WITH ( атрибут [. ...] ) ]. В PostgreSQL 7.1.x аргумент атрибут может принимать два значения: iscachablen isstrict.
- i scachabl e. Оптимизатор может использовать предыдущие вызовы функций для ускоренной обработки будущих вызовов с тем же набором аргументов. Кэширование обычно применяется при работе с функциями, сопряженными с большими затратами ресурсов, но возвращающими один и тот же результат при одинаковых значениях аргументов.
- i sstri ct. Функция всегда возвращает NULL в случае, если хотя бы один из ее аргументов равен NULL. При передаче атрибута isstrict результат возвращается сразу, без фактического выполнения функции.
Примечание 1
PostgreSQL позволяет перегружать функции, то есть присваивать одно имя нескольким функциям, отличающимся по типу аргументов. Перегрузка позволяет связать с одним именем функции несколько выполняемых операций в зависимости от количества и типа аргументов.
Создание новых операторов
Создание новых операторов
Кроме пользовательских функций PoslgreSQL позволяет создавать пользовательские операторы. С технической точки зрения операторы всего лишь обеспечивают альтернативный синтаксис для вызова функций. Например, оператор сложения (+) в действительности вызывает одну из встроенных функций (numeri c_add() и т. д.). Пример:
booktown=# SELECT I + 2 AS by_operator. numeric_add(l,2) AS by_function;
by_operator [ by_function
3 | 3
(1 row)
Определение оператора сообщает, к какому типу данных относятся левый и правый операнды. Кроме того, в определении указывается функция, которой при вызове в качестве аргументов передаются операнды.
Создание оператора
Создание оператора
Новые операторы создаются командой SQL CREATE OPERATOR. Синтаксис команды
CREATE OPERATOR:
CREATE OPERATOR оператор ( PROCEDURE = функция
[. LEFTARG = тип! ]
[. RIGHTARG = тип2 ]
[. COMMUTATOR = коммутатор ]
[. NEGATOR = инвертор ]
[. RESTRICT = функция ограничения ]
[. JOIN = функция_обьединения ]
[. HASHES ]
[. SORT1 = левдя_сортировкд ]
[. SORT2 = правая_сортировка ] )
В этом определении оператор — символ нового оператора, а функция — имя функции, вызываемой этим оператором. Остальные секции не обязательны, хотя в определении должна присутствовать хотя бы одна из секций LEFTARG или RIGHTARG. Оператор может состоять из следующих символов:
*-*/<>=~!@#*Л&|-?$
Примечание 2
Примечание 2
За дополнительной информацией об остальных секциях команды CREATE OPERATOR и ограничениях на символы операторов обращайтесь к документации.
Если в команде CREATE OPERATOR указан только тип данных LEFTARG, оператор работает только с левым операндом (константой или идентификатором). И наоборот, если указан только тип RIGHTARG, оператор работает только с правым операндом. При указании обоих типов данных, LEFTARG и RIGHTARG, оператор работает с обоими операндами, левым и правым.
Хорошим примером встроенного оператора, использующего только левый операнд, является оператор факториала (!), а оператор сложения работает с обоими операндами. Количество аргументов функции, указанной в команде CREATE OPERATOR, должно соответствовать использованию ключевых слов LEFTARG и RIGHTARG (один или два аргумента). Более того, типы аргументов функции должны соответствовать типам, указанным в команде CREATE OPERATOR.
В листинге 7.53 создается оператор !#, левый операнд которого передается функции is_zero() (см. листинг 7.49). Следовательно, обозначение х !# эквивалентно вызову функции is_zero(x).
Создание полей со значениямимассивами
Создание полей со значениями-массивами
Чтобы создать простейшее поле-массив, включите в команду CREATE TABLE или ALTER TABLE пару квадратных скобок после имени поля. Квадратные скобки показывают, что вместо одного значения в поле может храниться массив указанного типа. Например, команда для создания поля single_array типа type выглядит так:
single_array type[] -- Одномерный массив
Дополнительные квадратные скобки определя ют многомерные массивы, то есть «массивы массивов». Пример:
mu1ti_array type[][] -- Многомерный массив
Теоретически в квадратных скобках можно указать целое число, чтобы созданный массив имел фиксированный размер (то есть всегда состоял из п элементов по указанному измерению и не более). Тем не менее в PostgreSQL 7.1.x это ограничение не соблюдалось, и на практике массив фиксированной длины ничем не отличался от обычного массива.
В листинге 7.16 создается таблица с именем favorite_books, связывающая целочисленный код работника с одномерным массивом строк books.
Создание последовательности
Создание последовательности
Последовательности создаются командой SQL CREATE SEQUENCE с положительным или отрицательным приращением. Синтаксис команды CREATE SEQUENCE:
CREATE SEQUENCE последовательность
[ INCREMENT приращение ]
[ MINVALUE минимум ]
[ MAXVALUE максимум ]
[ START начало ]
[ CACHE кэш ]
[ CYCLE ]
В этом определении единственный обязательный параметр последовательность определяет имя создаваемой последовательности. Значения последовательности .представляются типом Integer, поэтому максимальное и минимальное значения должны лежать в интервале от 2 147 483 647 до -2 147 483 647.
Ниже описаны необязательные секции команды CREATE SEQUENCE.
- INCREMENT приращение. Числовое изменение текущего значения последовательности. Используется при вызове для последовательности функции nextvaK). Отрицательное приращение создает убывающую последовательность. По умолчанию приращение равно 1.
- MINVALUE минимум. Минимальное допустимое значение последовательности. Попытка уменьшить текущее значение ниже заданного минимума приведет к ошибке или циклическому переходу к максимальному значению (если последовательность создавалась с ключевым словом CYCLE). По умолчанию минимальное значение равно 1 для возрастающих последовательностей или -2 147 483 647 для убывающих последовательностей.
- MAXVALUE максимум. Максимальное допустимое значение последовательности. Попытка увеличить текущее значение выше заданного максимума приведет к ошибке или циклическому переходу к минимальному значению. По умолчанию максимальное значение равно 2 147 483 647 для возрастающих последовательностей или -1 для убывающих последовательностей.
- START начало. Начальное значение последовательности, которым является любое целое число в интервале между минимальным и максимальным значениями. По умолчанию последовательность начинается с нижнего порога для возрастающих последовательностей или с верхнего порога для убывающих последовательностей.
- CACHE кэш. Возможность предварительного вычисления и хранения значений последовательности в памяти. Кэширование ускоряет доступ к часто используемым последовательностям. Минимальное значение, заданное по умолчанию, равно 1; увеличение объема кэша приводит к увеличению числа кэшируемых значений.
- CYCLE. При достижении нижнего или верхнего порога последовательность продолжает генерировать новые значения. В этом случае она переходит к минимальному значению (для возрастающих последовательностей) или к максимальному значению (для убывающих последовательностей).
Создание производной таблицы
Создание производной таблицы
Производная таблица создается командой SQL CREATE TABLE, в которую включается секция INHERITS. Секция состоит из ключевого слова INHERITS и имени базовой таблицы (или нескольких таблиц).
Часть команды CREATE TABLE, относящаяся к наследованию, выглядит так:
CREATE TABLE производная_таблица определение
INHERITS ( базовая_таблица [. ...] )
В этом определении производная таблица — имя создаваемой таблицы, определение — полное определение таблицы со всеми стандартными секциями команды CREATE TABLE, а базовая _таблица — таблица, структура которой наследуется новой таблицей. Дополнительные имена базовых таблиц перечисляются через запятую.
В листинге 7.11 создается таблица distinguished_authors, определение которой состоит из единственного текстового поля award. Поскольку в команде создания таблицы указано ключевое слово INHERITS, таблица содержит четыре поля — одно собственное и три унаследованных.
Создание триггера
Создание триггера
Триггер создается на основе существующей функции. PostgreSQL позволяет создавать функции на разных языках программирования, в том числе на SQL, PL/ pgSQL и С. В PostgreSQL 7.1.x триггеры могут вызывать функции, написанные на любом языке, но за одним исключением: функция не может быть полностью реализована на SQL.
В определении триггера указывается, должна ли заданная функция вызываться до или после выполнения некоторой операции с таблицей. Синтаксис определения триггера выглядит так:
CREATE TRIGGER триггер { BEFORE | AFTER } { событие [ OR событие ...]}
ON таблица
FOR EACH { ROW STATEMENT }
EXECUTE PROCEDURE функция ( аргументы )
Ниже приводятся краткие описания компонентов этого определения.
- CREATE TRIGGER триггер. В аргументе триггер указывается произвольное имя создаваемого триггера. Имя может совпадать с именем триггера, уже существующего в базе данных — при условии, что этот триггер установлен для другой таблицы. Кроме того, по аналогии с большинством других несистемных объектов баз данных, имя триггера (в сочетании с таблицей, для которой он устанавливается) должно быть уникальным лишь в контексте базы данных, в которой он создается.
- { BEFORE AFTER }. Ключевое слово BEFORE означает, что функция должна выполняться перед попыткой выполнения операции, включая все встроенные проверки ограничений данных, реализуемые при выполнении команд INSERT и DELETE. Ключевое слово AFTER означает, что функция вызывается после завершения операции, приводящей в действие триггер.
- { событие [ OR событие ... ] }. События SQL, поддерживаемые в PostgreSQL При перечислении нескольких событий в качестве разделителя используется ключевое слово OR.
- ON таблица. Имя таблицы, модификация которой заданным событием приводит к срабатыванию триггера.
- FOR EACH { ROW STATEMENT }. Ключевое слово, следующее за конструкцией FOR EACH и определяющее количество вызовов функции при наступлении указанного события. Ключевое слово ROW означает, что функция вызывается для каждой модифицируемой записи. Если функция должна вызываться всего один раз для всей команды, используется ключевое слово STATEMENT.
- EXECUTE PROCEDURE функция ( аргументы ). Имя вызываемой функции с аргументами.
Примечание 3
Создание триггеров разрешено только владельцу базы данных или суперпользователю.
Механизм ограничений PostgreSQL позволяет реализовать простое сравнение данных со статическими значениями, но иногда проверка входных данных должна производиться по более сложным критериям. Это типичный пример ситуации, в которой удобно воспользоваться триггером.
Проверка входных данных с применением триггеров может осуществляться перед вставкой данных в таблицу или перед их обновлением в таблице. Функция триггера может убедиться в том, что новые данные удовлетворяют сложной системе ограничений, и даже вернуть признак ошибки через систему регистрации ошибок PostgreSQL.
Предположим, вы написали на процедурном языке функцию, которая проверяет данные, переданные при вызове команды INSERT или UPDATE для таблицы shipments, и затем обновляет таблицу stock, снимая поставленный товар со складского учета. Такую функцию можно написать на любом языке, поддерживаемом PostgreSQL (кроме «чистого» SQL, о чем говорилось выше).
Прежде всего функция убеждается в том, что переданный код покупателя (customerj d) и код ISBN (i sbn) присутствуют в таблицах customers и ech ti ons. Если хотя бы один из кодов отсутствует, функция возвращает признак ошибки. Если оба кода присутствуют в таблицах, команда SQL выполняется, и после успешного завершения количество товара на складе в таблице stock автоматически уменьшается в соответствии с объемом поставки.
Триггер, создаваемый в листинге 7.35, срабатывает непосредственно перед выполнением команды INSERT или UPDATE в таблице shi pments. Триггер вызывает функцию check_sh1pment addition() для каждой изменяемой записи.
Срезы
Срезы
В PostgreSQL также поддерживается возможность создания срезов при выборке из массива. Срез аналогичен обычному обращению к элементам по индексу, но он описывает интервал значений. Срез задается парой целочисленных индексов, разделенных двоеточием и заключенных в квадратные скобки. Например, конструкция [2:5] описывает второй, третий, четвертый и пятый элемент заданного массива. Результат среза возвращается в виде константы-массива, которая фактически описывает подмножество элементов исходного массива (впрочем, срез может содержать все элементы исходного массива).
В листинге 7.24 выбираются первые два элемента массива books в записях таблицы favorite_books. Хотя первая запись содержит только одно название книги, оно возвращается в виде массива из одного элемента.
Атрибуты последовательностей
Таблица 7.1. Атрибуты последовательностей
| Атрибут | Тип |
| sequence name | name |
| last_value | integer |
| increment by | integer |
| max value | integer |
| min value | integer |
| cache value | integer |
| log cnt | integer |
| is_cycled | "char" |
| is called | "char" |
Таблица shipments
Таблица 7.2. Таблица shipments
| Поле | Тип | Модификатор |
| Id | Integer | NOT NULL DEFAULT nextval ( 'shipments^ship id seq1) |
| customerjd | Integer | |
| isbn | text | |
| ship_date | timestamp with time zone |
CREATE TABLE shipments
(id integer DEFAULT nextval ('shipments_shipjd_seq')
PRIMARY KEY. customerjd integer, isbn text. ship_date timestamp)
В качестве значения по умолчанию для поля id назначается результат вызова nextval () для последовательности shi pments_shi p_i d_seq. Таким образом, при вставке записей без указания поля id значение автоматически генерируется по результату вызова функции.
ВНИМАНИЕ
Простая установка ограничения DEFAULT не гарантирует его применения. Пользователь способен вручную задать любое значение, что может привести к потенциальному нарушению уникальности в будущем. Для предотвращения конфликтов можно воспользоваться триггером. За дополнительной информацией обращайтесь к подразделу «Триггеры» этого раздела.
После вызова функции nextval О для последовательности в некотором сеансе (то есть подключении к PostgreSQL) функция currval () возвращает значение, полученное при предыдущем вызове nextval () в активном сеансе.
Примечание 2
Примечание 2
Текущее значение последовательностей ассоциируется с определенным сеансом, чтобы одновременные обращения со стороны нескольких пользователей не приводило к ошибкам. Два пользователя могут работать с одной последовательностью в разных сеансах, но при этом функция currval () возвращает последнее текущее значение последовательности для того сеанса, в котором она была вызвана.
В листинге 7.31 в таблицу shi pments вставляется новая запись, в которой не указано значение поля id. В этой ситуации используется значение по умолчанию, которое (см. табл. 7.2) определяется результатом приращения последовательности
shipments_ship_id_seq функцией nextvaK).
Затем функция currva() используется для выборки только что вставленной записи.
Таблица pgjrigger
Таблица 7.3. Таблица pgjrigger
| Поле | Тип |
| tgrelid | old |
| tgname | name |
| tgfoid | old |
| tgtype | smallint |
| tgenabled | boo'i ean |
| tgisconstraint | boolean |
| tgconstrname | name |
| tgconstrrelid | oid |
| tgdeferrable | boolean |
| tginltdef erred | boolean |
| tgnargs | small int |
| tgattr | int2vector |
| tgargs | bytea |
В поле tgrel id хранится идентификатор отношения, с которым связан данный триггер. Значение относится к типу oid и соответствует содержимому поля rel f i I enode системной таблицы pg_cl ass. В поле tgname хранится имя триггера, указанное в команде CREATE TRIGGER при его создании.
Типы индексов
Типы индексов
Необязательная секция USING задает реализуемый тип индекса. В PostgreSQL 7.1.x поддерживаются три типа индексов:
- В-дерево;
- R-дерево;
- кэш.
Реализация R-дерева, основанная на квадратичном разбиении по алгоритму Гуттмана (Guttman), применяется главным образом при операциях с геометрическими типами данных. Реализация хэша основана на алгоритмах линейного хэширования Литвина (Litwin), которые традиционно используются для индексов с частой проверкой равенства (то есть ориентированы на оператор =).
На момент написания книги в PostgreSQL версии 7.1.x реализация индексов на основе В-дерева значительно превосходила остальные типы но универсальности и широте возможностей. В-дерево рекомендуется использовать вместо хэша даже при прямых сравнениях оператором =. Хэш поддерживается в первую очередь по соображениям совместимости, хотя ничто не мешает вам выбрать эту реализацию, если вы твердо уверены в выигрыше от перехода на нее от В-дерева.
Как сказано выше, реализацию на основе R-дерева рекомендуется использовать для индексации геометрических типов данных, но при этом необходимо помнить о специфике этого типа. Например, для R-дерева нельзя построить уникальный индекс или провести индексацию по нескольким полям. В таких случаях лучше положиться на реализацию В-дерева, обладающую более широкими возможностями.
Тип индекса задается в секции USING при помощи ключевых слов BTREE, RTREE и HASH. По умолчанию используется тип BTREE.
В листинге 7.4 создается таблица с именем polygons, предназначенная для хранения геометрических данных типа polygon. Затем для поля shape создается индекс spaci a I _1 ndex типа RTREE.
Транзакции и курсоры
Транзакции и курсоры
В PostgreSQL используется специфический подход к обработке транзакций в базах данных. В терминологии SQL транзакцией называется процесс синхронизации результатов выполнения команды с состоянием данных в базе. Данные не записываются на диск немедленно, а лишь отражаются в «текущей» информации состояния, хранящейся в базе. В результате фиксации транзакции последствия выполнения команды окончательно фиксируются в текущем состоянии базы данных.
Возникает очевидная проблема — что произойдет, если два пользователя одновременно попытаются зафиксировать взаимоисключающие изменения в одном объекте базы данных? В некоторых СУБД подобные конфликты предотвращаются путем блокировки (locking).
Блокировкой называется механизм, запрещающий выборку из объекта базы данных на время его модификации, и наоборот. Применение блокировки связано с очевидными проблемами из области быстродействия. Например, выборка заблокированных данных становится невозможной до момента завершения обновления.
В PostgreSQL используется механизм MVCC (Multi-Version Concurrency Control), позволяющий выполнять команды SQL в отложенных транзакционных блоках. Таким образом, каждое подключение к серверу PostgreSQL до фиксации результатов фактически поддерживает временный «образ» объектов базы данных, модифицируемых в транзакцпопном блоке.
Если в программе отсутствует команда начала транзакциопного блока, все команды SQL, передаваемые PostgreSQL, фиксируются автоматически, то есть база данных синхронизируется с. результатами команд сразу же после их выполнения. Тем не менее при явном создании транзакщюнного блока изменения в базе данных остаются невидимыми для других пользователей вплоть до фиксации. Таким образом, появляется возможность одновременного внесения изменений в разные объекты базы данных. Далее все изменения либо фиксируются, либо откатываются (отменяются).
При откате транзакции все объекты возвращаются к состоянию, в котором они находились до начала транзакционпого блока. Такая возможность может пригодиться при восстановлении после незавершенных операций или при отмене любых частичных изменений. Отмененные транзакции не фиксируются в базе данных, и другие пользователи даже не замечают последствий незавершенной транзакции.
В PostgreSQL также поддерживаются курсоры — универсальный и гибкий механизм ссылок на выполненные запросы SQL. Курсор позволяет перебрать содержимое итогового набора и включить в выборку только некоторые из полученных записей. При правильном использовании курсоры повышают эффективность работы со статическими наборами записей в приложениях. Курсоры выполняются только в транзакционных блоках.
В следующем подразделе описаны основные принципы работы с транзакциями и курсорами. В частности, в нем рассматриваются команды создания, фиксации и отката транзакций, а также способы объявления, перемещения и выборки в курсорах.
Транзакционные блоки
Транзакционные блоки
Транзакционные блоки создаются командой SQL BEGIN, за которой могут следовать необязательные ключевые слова WORK или TRANSACTION. Эти ключевые слова делают команду более наглядной, но никак не влияют на работу ее пли транзакци-онного блока.
В листинге 7.38 приведен пример создания транзакционного блока в базе данных booktown.
Триггеры
Триггеры
Довольно часто перед некоторыми событиями SQL или после них должны выполняться определенные операции — например, проверка логической целостности данных, заносимых в базу, предварительное форматирование данных перед вставкой или модификация других таблиц, логически обусловленная удалением или модификацией записей. Традиционно такие операции выполнялись на программном уровне приложением, подключившимся к базе данных, а не самой СУБД.
В PostgreSQL поддерживаются нестандартные расширения, называемые триггерами (trigger) и упрощающие взаимодействие приложения с базой данных. Триггер определяет функцию, которая должна выполняться до или после некоторой операции с базой данных. Триггеры реализуются на языке С, PL/pgSQL или любом другом функциональном языке (кроме SQL), который может использоваться в PostgreSQL для определения функций. Дополнительная информация о создании функций приведена в разделе «Расширение PostgreSQL» этой главы, а языки PL/ pgSQL описаны в главе 11.
ВНИМАНИЕ
Триггеры относятся к числу специфических расширений PostgreSQL, поэтому их не рекомендуется использовать в решениях, требующих высокой степени совместимости с другими РСУБД.
Триггеры срабатывают при выполнении с таблицей команды SQL INSERT, UPDATE или DELETE.
Удаление индекса
Удаление индекса
Для удаления индексов из таблицы используется команда DROP INDEX. Синтаксис команды DROP INDEX: DROP INDEX индекс [. ...]
В качестве параметра команде передается имя удаляемого индекса. Допускается одновременное удаление нескольких индексов, перечисленных через запятую. В листинге 7.6 удаляется индекс upper_title_idx, созданный в листинге 7.5.
Удаление ограничений
Удаление ограничений
В PostgreSQL 7.1.x не поддерживается прямое удаление ограничений из таблицы. Добиться нужного результата можно лишь одним способом — создать копию таблицы, практически полностью повторяющую оригинал, но не содержащую удаляемых ограничений. Данные копируются из исходной таблицы в новую, после чего таблицы переименовываются командой ALTER TABLE и копия заменяет оригинал.
ВНИМАНИЕ
Применяя этот прием, следует учитывать, что кто-то из пользователей может подключиться к базе данных и работать с модифицируемыми таблицами. Вставка или любые модификации данных в процессе копирования недопустимы; таким образом, если таблица активно используется, вы можете временно запретить подключения к PostgreSQL, внести необходимые изменения и перезапустить систему.
В листинге 7.10 снятие ограничений продемонстрировано на примере ограничения FOREIGN KEY с именем legal_subjects, установленного для таблицы books (см. листинг 7.9). Обратите внимание на удаление индекса books_1d_pkey перед созданием новой таблицы, что позволяет создать таблицу с индексом books_id_pkey. На самом деле это не обязательно, но имя индекса первичного ключа лучше сохранить.
Удаление оператора
Удаление оператора
Операторы удаляются командой DROP OPERATOR. Выполнение этой команды разрешено либо пользователю, создавшему оператор, либо суперпользователю PostgreSQL.
ВНИМАНИЕ
Команда DROP OPERATOR применима не только к пользовательским, но и к встроенным операторам, поэтому при выполнении этой команды с правами суперпользователя необходимо действовать очень осторожно.
Так как операторы определяются не только именем, но и типом операндов, в команде DROP OPERATOR необходимо задать типы левого и правого операндов. Если какой-либо из операндов не используется, вместо типа указывается ключевое слово NONE.
Синтаксис команды DROP OPERATOR:
DROP OPERATOR оператор ( { левый_тип \ NONE } .
{ правый_тип \ NONE } )
В листинге 7.57 удаляется версия оператора ! #, работающая с двумя операндами.
Удаление последовательности
Удаление последовательности
Команда SQL DROP SEQUENCE удаляет последовательность или несколько последовательностей одновременно. Синтаксис команды DROP SEQUEICE: DROP SEQUENCE последовательность [. ...]
В качестве параметра команде передается имя удаляемой последовательности. Допускается одновременное удаление нескольких последовательностей, перечисленных через запятую.
В листинге 7.33 удаляется последовательность shipments_ship_id_seq.
Удаление триггера
Удаление триггера
Команда DROP TRIGGER удаляет триггер из базы данных. Удаление триггеров, как и их создание командой CREATE TRIGGER, может выполняться только владельцем триггера или суперпользователем.
Синтаксис удаления существующих триггеров:
DROP TRIGGER имя ON таблица
В листинге 7.36 приведен пример удаления триггера check_shipment, установленного для таблицы shipments.
Уничтожение функций
Уничтожение функций
Функции уничтожаются владельцем или суперпользователем при помощи команды SQL DROP FUNCTION. Синтаксис команды DROP FUNCTION:
DELETE FUNCTION имя ( [ тип_аргуменга [. ...] ] ):
В листинге 7.52 приведен пример удаления функции 1sbn_to_t1tle(text). Обратите внимание: типы аргументов должны указываться обязательно, даже если функция и не перегружалась.
Уникальные индексы
Уникальные индексы
Создание индекса с ключевым словом UNIQUE говорит о том, что индекс является уникальным, то есть индексируемое поле (или поля) не может содержать повторяющихся значений. Фактически создание уникального индекса эквивалентно созданию таблицы с ограничением уникальности (см. ниже подраздел «Ограничения в таблицах» в разделе «Нетривиальное использование таблиц»).
В листинге 7.3 для поля name таблицы publ ishers создается уникальный индекс unique_publ IsheMdx. Это означает, что в таблице не могут присутствовать два издательства с одинаковыми названиями.
Вставка значений в полямассивы
Вставка значений в поля-массивы
В PostgreSQL предусмотрен специальный синтаксис вставки нескольких значений в одно поле. Этот синтаксис основан на определении массивов-констант. Как упоминалось в главе 3, массив-константа (предназначенный для ссылки на массивы PostgreSQL в командах SQL) состоит из фигурных скобок, апострофов и запятых, заключенных в апострофы. Кавычки нужны только при работе с массивами строк. Таким образом, обобщенная форма массива-константы выглядит так:
'{ "текст" [. ...] }' -- массив строк
'{ число [. ...]}' -- числовой массив
В этих примерах использованы строковые и числовые массивы, но поле может определяться как массив произвольного типа (включая типы boolean, date и time). Как правило, если для описания величины в скалярном контексте должны использоваться апострофы (например, в строковых константах или данных типа timestamp), в контексте массива эта величина заключается в кавычки.
В листинге 7.18 в таблицу favorite_books вставляются две записи. Первая команда создает массив с одним элементом для работника с кодом 102, а вторая запись создает массив с двумя элементами для работника с кодом 103. В обеих командах INSERT используются массивы-константы.
Выборка из курсора
Выборка из курсора
Выборка записей из курсора производится командой FETCH. Синтаксис команды
FETCH:
FETCH [ FORWARD BACKWARD | RELATIVE ]
[ число ALL | NEXT | PRIOR ]
{ IN | FROM } курсор
В этом объявлении курсор — имя курсора, из которого производится выборка записей. Курсор всегда указывает па «текущую» позицию итогового набора выполненной команды, а в выборке могут участвовать записи, находящиеся до или после текущей позиции. Направление выборки определяется ключевыми словами FORWARD и BACKUARD, но умолчанию используется прямая выборка (FORWARD). Ключевое слово RELATIVE не обязательно и поддерживается лишь для совместимости со стандартом SQL92.
ВНИМАНИЕ
В команде также может использоваться ключевое слово ABSOLUTE, но в PostgreSQL 7.1.x возможности абсолютного позиционирования и выборки в курсорах не реализованы. Курсор использует относительное позиционирование и выводит сообщение о том, что абсолютное позиционирование не поддерживается.
За ключевым словом, идентифицирующим направление, может указываться следующий аргумент — количество записей. Допускается указание конкретного числа записей (в виде целочисленной константы) или одного из нескольких ключевых слов. Ключевое слово ALL означает, что команда возвращает все записи, начиная с текущей позиции курсора. С ключевым словом NEXT (используется по умолчанию) команда возвращает следующую запись от текущей позиции курсора. С ключевым словом PRIOR возвращается запись, находящаяся перед текущей позицией курсора.
Ключевые слова IN и FROM эквивалентны, из них в команде должно присутствовать одно.
В листинге 7.43 выбираются первые четыре записи итогового набора, на который ссылается курсор all_books. Направление не указано, поэтому по умолчанию используется ключевое слово FORWARD. Далее команда FETCH с ключевым словом NEXT выбирает пятую запись, после чего команда FETCH с ключевым словом PRIOR снова возвращается к четвертой записи.
Выборка из полеймассивов
Выборка из полей-массивов
При выборке из поля-массива весь массив возвращается в формате константы, описанном в предыдущем разделе. В листинге 7.20 команда SELECT выбирает все элементы массивов в поле books таблицы favorite_books.
Закрытие курсора
Закрытие курсора
Команда CLOSE закрывает ранее открытый курсор. Курсор также автоматически закрывается при выходе из транзакционного блока, в котором он находится, при фиксации транзакции командой COMMIT или ее откате командой ROLLBACK. Синтаксис команды CLOSE (курсор — имя закрываемого курсора):
CLOSE курсор
В листинге 7.45 курсор all_books закрывается и освобождает занимаемую им память, вследствие чего данные курсора становятся недоступными.
Базы данных: Разработка - Управление - Excel
- Базы данных
- Разработка баз данных
- СУБД и базы данных
- Управление базами данных
- Классика баз данных
- Софт для создания базы данных
- SQL
- Access
- FoxProо
- Расширенная оптимизация подзапросов в Oracle
- Informix
- Линтер
- Postgres
- СУБД DB2
- InterBase
- Excel
- Таблицы Excel
- Справка Excel
- Программирование в Excel
- Деньги в Excel
- Задачи Excel