Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Объектно-реляционная СУБД PostgreSQL. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
12.08.2026
Размер:
787 Кб
Скачать

в качестве шаблона при создании новой БД может использоваться и существующая БД, тогда её имя явно указывается в запросе:

CREATE DATABASE имя_БД TEMPLATE имя_шаблона;

Если новая БД создаётся в pgAdmin, то на панели SQL мы увидим текст соответствующего запроса. Например, при создании БД "test" для роли "testuser" будет сгенерирован запрос:

CREATE DATABASE test WITH OWNER = testuser

ENCODING = 'UTF8' TABLESPACE = pg_default

LC_COLLATE = 'Russian_Russia.1251' LC_CTYPE = 'Russian_Russia.1251'

CONNECTION LIMIT = -1;

Поясним значения атрибутов запроса.

WITH OWNER задаёт пользователя БД – роль "testuser".

ENCODING – задаёт кодировку строковых данных utf-8 (один из вариантов кодировки Unicode).

TABLESPACE = pg_default – задаёт папку для штатного размещения объектов БД (сама папка указывается при установке PostgreSQL). Пользователь может указать свой вариант размещения объектов БД, предварительно создав табличное пространство запросом

CREATE TABLESPACE имя LOCATION путь_к_папке;

Список всех табличных пространств содержится в системной таблице pg_tablespace.

Атрибут локализации LC_COLLATE определяет настройки сравнения строк и символов, влияет на сортировку (указанное в запросе значение атрибута позволяет правильно сравнивать символы кириллицы).

Атрибут локализации LC_CTYPE отвечает за классификацию символов и различия в их регистре (указанное в запросе значение атрибута позволяет правильно классифицировать символы кириллицы).

21

Атрибут CONNECTION LIMIT задаёт ограничение на число подключений к БД. По умолчанию значение атрибута равно -1, что соответствует неограниченному числу подключений. Однако и при неограниченном числе подключений к БД можно ограничить число подключений для конкретного пользователя при создании роли.

Б) Создание таблицы

Для создания структуры таблицы в БД используется запрос вида CREATE TABLE, для её модификации – запрос вида ALTER TABLE, а для удаления – запрос DROP TABLE имя_таблицы;.

Синтаксис запроса CREATE TABLE :

CREATE TABLE [IF NOT EXISTS] имя_таблицы

(

имя_поля тип_поля ограничения_поля,

имя_поля тип_поля ограничения_поля,

ограничения_таблицы

);

В качестве ограничений поля можно использовать следующие варианты:

NOT NULL – поле, обязательное для заполнения (непустое поле);

UNIQUE – повторяющиеся значения не допускаются (исключение – значение NULL, т.е., пустое значение может многократно появляться в поле таблицы);

DEFAULT значение – значение по умолчанию. Это значение получит

поле, если при вставке записи в таблицу оператором INSERT данное поле будет пропущено;

– CHECK условие – задаёт ограничение на значение данного поля. Заданное условие проверяется при выполнении команд INSERT или UPDATE. В условии CHECK может использоваться только поле, для которого устанавливается ограничение. Если же в условии CHECK необходимо обращаться к разным полям таблицы, то его нужно вынести в ограничения таблицы;

22

PRIMARY KEY – простой первичный ключ таблицы. В случае составного ключа его определение также выносится в ограничения таблицы;

REFERENCES таблица [ (поле) ] – ссылка на поле в другой

таблице. Если это поле является простым первичным ключом, то имя поля можно не указывать.

Пример. Создадим таблицу info следующим SQL-запросом:

CREATE TABLE info

(

id int PRIMARY KEY, name text UNIQUE,

birthday date CHECK (birthday>'1900-01-01'::date)

);

и посмотрим на результат в окне Панель SQL pgAdmin:

CREATE TABLE info

(

id integer NOT NULL, name text,

birthday date,

CONSTRAINT info_pkey PRIMARY KEY (id), CONSTRAINT info_name_key UNIQUE (name) CONSTRAINT info_birthday_check CHECK (birthday >

'1900-01-01'::date)

)

WITH ( OIDS=FALSE

);

ALTER TABLE info OWNER TO postgres;

Напомним, что аббревиатура OIDS расшифровывается как Object IDentifierS

– «идентификаторы объектов». PostgreSQL использует эти значения в качестве первичных ключей для своих системных таблиц. OIDs не добавляются в таблицы, созданные пользователем, если только при создании таблицы не указать WITH (OIDS = TRUE).

23

Поле id (от слова identifier – идентификатор) в данном примере используется как первичный ключ, но не несёт никакой смысловой нагрузки. Общепринятая практика в таких случаях – использовать для этого поля атрибуты smallserial, serial или bigserial, которые позволяют автоматически присваивать записям таблицы последовательные номера.

Имена полей подчиняются соглашениям, принятым в языках программирования для идентификаторов, т.е., могут содержать буквенные и цифровые символы и символ подчёркивания. Часто разработчики ограничиваются только строчными символами латиницы, однако PostgreSQL поддерживает весь указанный выше набор символов, но с некоторыми особенностями. Так, например, прописные английские буквы автоматически преобразуются в строчные. При необходимости использовать в именах полей прописные символы английского алфавита необходимо заключать имена полей в двойные кавычки, например использовать "Name" вместо Name. Кавычки также нужны, если имя поля содержит пробелы. Если же имена будут содержать символы кириллицы, то PostgreSQL сам возьмёт эти имена в кавычки. Проиллюстрируем сказанное несколькими примерами.

1. Создадим таблицу Персонал (ТабНомер, ФИО, Дата рождения) с ключевым полем ТабНомер.

CREATE TABLE Персонал ( ТабНомер integer PRIMARY KEY, ФИО text not null, ДатаРождения date,

Должность text

);

PostgreSQL преобразует данный запрос в следующий вид:

CREATE TABLE "Персонал"

(

"ТабНомер" integer NOT NULL, "ФИО" text NOT NULL, "ДатаРождения" date,

24

"Должность" text,

CONSTRAINT "Персонал_pkey" PRIMARY KEY ("ТабНомер")

)

WITH ( OIDS=FALSE

);

ALTER TABLE "Персонал" OWNER TO postgres;

Попробуем добавить в таблицу поле "Номер Отдела":

ALTER TABLE Персонал

ADD COLUMN Номер отдела integer;

При выполнении этого запроса получим сообщение об ошибке синтаксиса. Добавим теперь кавычки вокруг названия поля:

ALTER TABLE Персонал

ADD COLUMN "Номер отдела" integer;

и запрос будет выполнен. Поскольку использование пробелов в именах не очень удобно, переименуем это поле запросом

ALTER TABLE Персонал

RENAME "Номер отдела" TO НомерОтдела;

2. Создадим таблицу Отделы (НомерОтдела, НазваниеОтдела):

CREATE TABLE Отделы ( НомерОтдела integer, НазваниеОтдела text,

CONSTRAINT pk_Отделы PRIMARY KEY(НомерОтдела)

);

Сделаем теперь поле Персонал.НомерОтдела внешним ключом, ссылающимся на поле НомерОтдела таблицы Отделы:

ALTER TABLE Персонал

ADD CONSTRAINT fk_НомерОтдела

FOREIGN KEY (НомерОтдела)

REFERENCES Отделы(НомерОтдела);

25

PostgreSQL преобразует данный запрос в следующий вид:

ALTER TABLE "Персонал"

ADD CONSTRAINT "fk_НомерОтдела" FOREIGN KEY ("Номер Отдела")

REFERENCES "Отделы" ("НомерОтдела") MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION;

Атрибут MATCH определяет, могут ли в полях, на которые ссылается внешний ключ, появляться пустые значения (по умолчанию значение атрибута – SINGLE – разрешает сочетать NULL и не-NULL значения).

Атрибуты ON UPDATE, ON DELETE определяют действие с записью при обновлении ключа или удалении записи в связанной таблице.

По умолчанию выполняется действие NO ACTION: при попытке удаления записи или изменения тех её полей, на которые ссылается внешний ключ, ничего не делать. В этом случае ни удаление записи, ни её обновление не выполняется, а выдаётся сообщение об ошибке.

Например, если попытаться удалить какой-либо отдел из таблицы Отделы или хотя бы поменять значение ключа НомерОтдела в этой таблице, мы получим следующее сообщение:

ОШИБКА: UPDATE или DELETE в таблице "Отделы" нарушает

ограничение внешнего ключа "fk_НомерОтдела" таблицы

"Персонал".

Таким образом, чтобы удаление какой-либо записи из таблицы Отделы выполнилось корректно, необходимо будет сначала явно удалить все записи о сотрудниках данного отдела («уволить» их) или изменить НомерОтдела для этих сотрудников на уже существующий («перевести» сотрудников в другой отдел).

Чтобы изменить поведение по умолчанию, следует выбрать для атрибутов ON UPDATE, ON DELETE один из следующих вариантов:

CASCADE: удаляются или изменяются все связанные записи из подчинённой таблицы. В этом случае, например, при изменении значения поля НомерОтдела в таблице Отделы автоматически изменится и поле НомерОтдела у тех сотрудников, которые работают в этом отделе. С опцией CASCADE следует

26

обращаться крайне осторожно, так как её использование может привести к удалению большого количества связанных записей.

SET DEFAULT: при удалении или изменении связанной записи установить поле внешнего ключа в значение по умолчанию, при этом удаления записей из подчинённой таблицы не происходит.

SET NULL: при удалении или изменении связанной записи установить поле внешнего ключа в NULL, при этом удаления записей из подчинённой таблицы не происходит.

3. Добавим в таблицу Персонал поле Оклад со значением по умолчанию 10000 рублей и условиями Оклад>=10000 И Оклад<=50000 рублей:

ALTER TABLE Персонал ADD COLUMN Оклад MONEY

DEFAULT 10000::money

CHECK(Оклад>=10000::money AND Оклад<=50000::money);

Здесь оператор ::тип означает преобразование значения к заданному типу, в частности, ::money преобразует числовое значение в денежный тип.

2.4.Манипулирование данными с помощью SQL-запросов

ВSQL-запросах манипулирования данными используются следующие операторы (часто называемые командами):

– оператор INSERT INTO – вставка записей в таблицу;

оператор DELETE FROM – удаление записей из таблицы;

оператор UPDATE – изменение данных в таблице.

Оператор INSERT INTO может изменять единовременно только одну таблицу, поэтому при заполнении таблиц многотабличной базы данных необходимо выбрать правильный порядок ввода записей. Например, прежде чем вводить данные о сотрудниках какого-либо отдела необходимо ввести данные о самом отделе.

27

Синтаксис оператора:

INSERT INTO имя_таблицы (список_полей)

VALUES (список_значений), (список_значений), … ;

Если задаются значения для всех полей таблицы, то список полей можно опускать. Если запись содержит поле с автоматической нумерацией, то его нужно исключить из списка полей.

Пример. Добавим в таблицу Отделы несколько записей:

INSERT INTO Отделы VALUES(1, 'Администрация'); INSERT INTO Отделы VALUES(2, 'Бухгалтерия'); INSERT INTO Отделы VALUES(3, 'Менеджеры');

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

Теперь можно добавить сотрудников в таблицу Персонал. Пусть мы хотим на первое место в списке значений поставить атрибут Должность. Тогда запросы на добавления сотрудников будут иметь следующий вид:

INSERT INTO Персонал (Должность, НомерОтдела, ФИО, ДатаРождения, ТабНомер)

VALUES

('Директор',1,'Иванов И.П.','1973-03-08',100), ('Бухгалтер',2,'Петрова М.И.','1988-06-24',200), ('Менеджер',3,'Кузнецов В.В.','1991-10-17',300);

Заметим, что запрос INSERT INTO не меняет порядок полей в таблице Персонал. В этом можно убедиться при просмотре содержимого заполненной таблицы.

Чтобы увидеть результат выполнения запроса, используем инструмент «Просмотр данных в выбранном объекте» (пиктограмма 7 на панели инструментов). На рис. 4 показан вид экрана при просмотре содержимого таблицы.

28

Рис. 4. Окно вывода содержимого таблицы Персонал

Замечания.

1.Порядок вывода колонок таблицы соответствует порядку полей, заданному при описании таблицы, но не порядку полей в запросе INSERT.

2.Значения поля Оклад установлены по умолчанию, заданному в ограничении DEFAULT, поскольку в запросе INSERT отсутствует поле Оклад.

Теперь изменим оклад директора и бухгалтера фирмы. Для этого используем оператор UPDATE. Синтаксис описания оператора:

UPDATE имя_таблицы

SET имя_поля_1 = выражение_1, имя_поля_2 = выражение_2,

WHERE условие_отбора_записей;

При написании запросов учтём, что величина оклада ограничена значением 50000 рублей (иначе получим сообщение об ошибке).

UPDATE Персонал SET Оклад = 50000::money

WHERE Должность = 'Директор';

UPDATE Персонал SET Оклад = 30000::money

WHERE Должность = 'Бухгалтер';

29

При заполнении данными таблицы, содержащей массивы и/или составные типы, используются фигурные скобки для значений-массивов и круглые – для значений составных типов.

Пример. Создадим тестовую таблицу

CREATE TABLE Test

(

num integer PRIMARY KEY, arr integer[],

rec complex

);

заполним две строки данными

INSERT INTO Test VALUES(1,'{3, 17, 21}',(0, -5));

INSERT INTO Test VALUES(2,'{-12, 94}',(21, 13));

и проверим содержимое таблицы (рис. 5).

Рис. 5. Окно вывода содержимого таблицы Test

2.5. Выборка данных с помощью SQL-запросов

Самой частой операцией при работе с базой данных является операция выборки данных. Для извлечения данных по заданному критерию, вычисления статистических показателей, сортировки результатов используется оператор SELECT. Из всех SQL-операторов он имеет наиболее сложную структуру.

Рассмотрим сначала синтаксис оператора SELECT:

SELECT [ALL|DISTINCT] * | список_полей/выражений [FROM табличное_выражение]

[WHERE условие_отбора_записей]

30

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]