Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Базы данных. Практический курс. В 2 частях. Ч.1. Объектно-реляционные базы данных на примере PostgreSQL 9.5. Учебное пособие.pdf
X
- •Введение
- •Контрольные вопросы
- •Создание базы данных
- •Создание таблиц
- •Создание последовательностей
- •Ввод данных
- •Оператор CREATE TABLE
- •Оператор ALTER TABLE
- •Операторы DROP TABLE и DROP
- •Создание индексов
- •Контрольные вопросы
- •Средства определения данных языка SQL
- •Средства запроса данных языка SQL
- •Чтение заданных столбцов из одиночной таблицы
- •Чтение заданных строк из одиночной таблицы
- •Чтение заданных строк и столбцов из одиночной таблицы
- •Сортировка результатов
- •Агрегатные функции и группировка
- •Оконные функции
- •Чтение данных из нескольких таблиц с применением вложенных запросов
- •Чтение данных из нескольких таблиц с помощью операции соединения
- •Объединения
- •Средства модификации данных языка SQL
- •Вставка данных, оператор INSERT
- •Изменение данных, оператор UPDATE
- •Удаление данных, оператор DELETE
- •Транзакции
- •SQL-представления
- •Использование представлений для скрытия столбцов и строк
- •Использование представлений для отображения вычисляемых столбцов
- •Использование представлений для скрытия сложного синтаксиса
- •SQL-запросы в прикладных программах
- •Хранимые процедуры
- •Триггеры
- •Использование триггеров для проверки допустимости вводимых данных
- •Триггер, обновляющий представление
- •Триггер, обеспечивающий ссылочную целостность
- •Модуль TABLEFUNC
- •Словарь метаданных
- •Контрольные вопросы
- •Функция ROW_NUMBER
- •Функция COALESCE
- •Числовые функции
- •Тригонометрические функции
- •Контрольные вопросы
- •Заключение
- •Библиографический список

Глава 4. Применение SQL 4.1. SQL-представления
ArtistName AreaCode PhoneNumber
Selma Warning 253 555-1234
Susan Wu 721 555-1234
Donald G. Gray 705 555-1345
Lynda Johnson 703 555-1000
Chris Wilkens 206 555-1234
Можно скрывать от просмотра и строки таблиц. Для этого в
определении представления должно присутствовать предложение
WHERE. Следующий оператор определяет представление, содержа-
щее имена и номера телефонов всех клиентов, проживающих в
штате Вашингтон:
CREATE VIEW BasicCustomerDataWa AS
SELECT Name, PhoneNumber
FROM CUSTOMER
WHERE State = ’WA’;
Результирующая таблица будет такая:
Name PhoneNumber
Jeffrey Janes 555-1345
Tiffany Twilight 555-1000
Fred Smathers 555-1234
Chris Wilkens 555-1234
Как и требовалось, в таблице присутствуют сведения только
о тех клиентах, которые проживают в штате Вашингтон. Данный
факт не является очевидным, поскольку столбец State не входит в
результат. Это может быть хорошо или плохо в зависимости от того,
как используется представление. Если оно используется только в
тех случаях, когда значение имеют лишь клиенты из Вашингтона,
это хорошо; в противном случае это будет дезориентировать пользователя, создавая впечатление, что кроме перечисленных персон,
у галереи больше нет клиентов.
4.1.2 Использование представлений для отображения вычисляемых столбцов
Еще одно применение представлений – отображение резуль-
татов вычислений, не прибегая к вводу формул пользователем. На-
71

4.1. SQL-представления Глава 4. Применение SQL
пример, следующее представление объединяет столбцы AreaCode и
PhoneNumber и форматирует результат:
CREATE VIEW CustomerPhone AS
SELECT Name,
(’(’ || AreaCode || ’)’) || PhoneNumber AS Phone
FROM CUSTOMER;
Допустим, пользователь вводит следующий запрос:
SELECT *
FROM CustomerPhone;
Результаты выполнения этого запроса будут следующими:
Name Phone
Jeffrey Janes (206)555-1345
David Smith (303)555-5434
Tiffany Twilight (206)555-1000
Fred Smathers (206)555-1234
Mary Beth Frederickson (303)555-1000
Selma Warning (253)555-1234
Susan Wu (721)555-1234
Donald G. Gray (705)555-1345
Lynda Johnson (703)555-1000
Chris Wilkens (206)555-1234
Выполнение необходимых вычислений в представлениях имеет два преимущества. Во-первых, это избавляет пользователей от
необходимости вводить математическое выражение, чтобы получить желаемый результат (а также от необходимости знать, как это
делается). Во-вторых, это обеспечивает единообразие результатов.
Если каждый разработчик, использующий вычисления, будет писать собственные выражения, то они, скорее всего, будут написаны
по-разному, из-за чего результаты будут иметь неодинаковый вид.
4.1.3 Использование представлений для скрытия сложного синтаксиса
Еще одно применение представлений – скрытие SQL-запросов
со сложным синтаксисом. Это может делаться для того, чтобы избавить разработчиков от необходимости вводить сложный запрос
всякий раз, когда им требуется определенное представление, или
72

Глава 4. Применение SQL 4.1. SQL-представления
для того, чтобы разработчики, не знающие SQL, могли тем не
менее воспользоваться преимуществами, которые предоставляют
сложные SQL-запросы. Кроме того, как и в случае использования
представлений для вычислений, это обеспечивает единообразие
результатов.
Два наиболее распространенных варианта использования
представлений в данной ипостаси – это скрытие соединений и скрытие вложенных запросов.
Предположим, что продавцам-консультантам галереи необходимо знать, какими художниками интересуется тот или иной клиент. Поскольку связь между сущностями CUSTOMER и ARTIST имеет вид N:M, она представлена в виде таблицы пересечения. Таким образом, чтобы отобразить сведения об интересах клиентов,
необходимо выполнить два соединения: сначала соединить таблицы CUSTOMER и CUSTOMER_ARTIST_INT, а затем полученный результат
соединить с таблицей ARTIST. Представление, содержащее эти два
соединения, конструируется с помощью следующего SQL-запроса:
CREATE VIEW CustomerInterests AS
SELECT C.Name AS Customer, A.Name AS Artist
FROM CUSTOMER C
JOIN CUSTOMER_ARTIST_INT CI
ON C.CustomerID = CI.CustomerID
JOIN ARTIST A
ON CI.ArtistID = A.ArtistID;
Данный запрос выполняет стандартное двойное соединение.
Обратите внимание на использование псевдонимов для таблиц
(С вместо CUSTOMER, CI вместо CUSTOMER_ARTIST_INT, A вместо ARTIST).
Такие псевдонимы упрощают соединения. Например, проще написать C.CustomerID = CI.CustomerID, чем CUSTOMER.CustomerID =
= CUSTOMER_ARTIST_INT.CustomerID. Использовать псевдонимы не
обязательно.
Также обратите внимание на переименование C.Name в
Customer и A.Name в Artist. Такое переименование выполнять необ-
ходимо, в противном случае в представлении оказались бы два
столбца с именем Name. СУБД не смогла бы различить эти два столбца и выдала бы ошибку при создании представления.
73

4.1. SQL-представления Глава 4. Применение SQL
Следующий оператор запрашивает данные из представления
CustomerInterests и сортирует результаты по столбцу Customer:
SELECT *
FROM CustomerInterests
ORDER BY Customer;
Результат получился следующий:
Customer Artist
Chris Wilkens Frings
Chris Wilkens Tobey
David Smith Tobey
Donald G. Gray Tobey
Fred Smathers Tobey
Lynda Johnson Tobey
Lynda Johnson Moos
Lynda Johnson Frings
Mary Beth Frederickson Frings
Mary Beth Frederickson Moos
Mary Beth Frederickson Tobey
Selma Warning Tobey
Selma Warning Miro
Tiffany Twilight Chagall
Tiffany Twilight Frings
Tiffany Twilight Tobey
Представления используются также для скрытия группировки и встроенных функций. Рассмотрим следующее определение
представления:
CREATE VIEW ArtistWorkNet AS
SELECT W.WorkID, Name, Title, Copy, AcquisitionPrice,
SalesPrice, (SalesPrice - AcquisitionPrice) AS NetPrice
FROM TRANSACTION T
JOIN WORK W
ON T.WorkID = W.WorkID
JOIN ARTIST A
ON W.ArtistID = A.ArtistID;
Данное представление соединяет таблицы TRANSACTION, WORK и
ARTIST и создает вычисляемый столбец NetPrice. С этим представ-
лением можно выполнять различные операции на языке SQL, как
если бы NetPrice был обычным столбцом таблицы. Например, что-
74

Глава 4. Применение SQL 4.1. SQL-представления
бы отобразить совокупную прибыль от продажи каждой картины,
можно использовать следующий оператор:
SELECT Name, Title, Copy, SUM(NetPrice) AS TotalNet
FROM ArtistWorkNet
GROUP BY Name, Title, Copy;
Результаты выполнения этого запроса показаны ниже:
Name Title Copy TotalNet
Tobey Mystic Fabric 105/135 5250.00
Miro Mi Vida 7/10 44300.00
Tobey Slow Embers NC 7750.00
Tobey Mystic Fabric 99/135 27550.00
Chagall Northwest by Night 37/50 24500.00
У представлений имеется еще одно важное применения – они
могут обеспечивать определенный уровень абстракции между приложением базы данных и реальными таблицами. Этот уровень абстракции может быть важен, когда источник данных может меняться. Чтобы понять, о чем идет речь, рассмотрим следующее
определение представления:
CREATE VIEW CustomerTable1 AS
SELECT *
FROM CUSTOMER;
В сущности, это представление присваивает таблице CUSTOMER
псевдоним CustomerTable1. Представление CustomerTable1 можно
обрабатывать точно таким же образом, как и таблицу CUSTOMER.
Если в коде приложения используется имя CustomerTable1,
то источник данных, на котором основано это представление, может меняться, не вызывая необходимости переписывать приложение. Следовательно, в определенный момент в будущем, если источником данных о клиентах станет другая таблица, например,
NEW_CUSTOMER, все, что потребуется сделать, – это переопределить
представление CustomerTable1 следующим образом:
CREATE VIEW CustomerTable1 AS
SELECT *
FROM NEW_CUSTOMER;
75

4.2. SQL-запросы в прикладных программах Глава 4. Применение SQL
Весь код приложения, в котором используется имя
CustomerTable1, без проблем будет работать с новым источником
данных.
Из-за потенциальной необходимости в изменении источников
данных некоторые организации никогда не предоставляют разработчикам доступ к реальным таблицам. Вместо этого используются
представления, базирующиеся на данных из этих таблиц. Такая
стратегия повышает гибкость для будущих проектов по разработке
баз данных и упрощает их перепроектирование.
4.2 SQL-запросы в прикладных программах
SQL-запросы можно встраивать в триггеры, хранимые процедуры и прикладные программы. Для того чтобы встроить
SQL-запросы в программный код, необходимо преодолеть два затруднения. Во-первых, нужен какой-то способ, позволяющий записывать результаты выполнения SQL-запросов в программные переменные. Это можно сделать по-разному. В одних случаях для этого используются объектно-ориентированные программы, в других
применяются более простые методы. Например, в PL/pgSQL (описание данного языка представлено далее) следующий оператор присваивает переменной rowcount значение, равное количеству строк
в таблице CUSTOMER:
SELECT COUNT(*) INTO rowcount
FROM CUSTOMER;
Вторая трудность заключается в несоответствии парадигм
SQL парадигмам языков программирования. Язык SQL оперирует
множествами: большинство запросов SQL возвращают таблицу или
набор строк. В отличие от этого, программы оперируют отдельными
элементами или строками. Из-за этого отличия оператор, подобный
приведенному ниже, не имеет смысла:
SELECT Name INTO custName
FROM CUSTOMER;
Если в таблице CUSTOMER имеется 100 строк, то запрос столбца
Name возвратит 100 значений, в то время как переменная custName
может принять только одно значение.
76

Глава 4. Применение SQL 4.3. Хранимые процедуры
Чтобы преодолеть это затруднение, результаты выполнения
SQL-запросов обрабатываются как коллекции. SQL-запрос возвращает набор строк. На первую строку помещается курсор, и данная
строка обрабатывается. Затем курсор перемещается на следующую
строку, и так далее, пока не будут обработаны все строки. Типичный
процесс обработки выглядит так:
Использовать
коллекцию SQL (SELECT * FROM CUSTOMER);Поместить
курсор на первую строку;
Пока курсор не вышел за пределы таблицы {
Присвоить custName значение столбца
Name в строке под курсором;
... Прочие операторы, использующие значение custName ...
Переместить курсор не следующую строку;
};
... Продолжение обработки...
Таким образом, строки, возвращенные SQL-запросом, обрабатываются по одной. Именно таким является принцип встраивания
SQL-запросов в программный код. Примеры будут представлены
далее.
4.3 Хранимые процедуры
Хранимая процедура (stored procedure) – это программа, которая выполняет некоторые действия с информацией в базе данных и при этом сама хранится в базе данных. В PostgreSQL хранимые процедуры можно писать на собственном языке программирования этой СУБД, носящим название PL/pgSQL (Procedural
Language/PostGres Structured Query Language – процедурное расширение языка SQL) или на таких языках, как PL/Perl, PL/Python
и PL/Tcl, дополнительно можно использовать PL/Java, PL/PHP, PL/Py,
PL/R, PL/Ruby, PL/Scheme, PL/sh и PL/V8, а также имеется поддержка загрузки C-совместимых модулей.
Хранимые процедуры могут иметь входные параметры и возвращать результаты. В отличие от триггерных функций (см. подраздел 4.4), которые принадлежат определенной таблице или пред-
77

4.3. Хранимые процедуры Глава 4. Применение SQL
ставлению, хранимые процедуры принадлежат базе данных в целом. Они могут вызываться любым процессом, использующим базу
данных, при условии, что у этого процесса есть достаточные права
доступа.
Хранимые процедуры используются для многих целей. Хотя
администраторы баз данных используют их для выполнения рутинных задач администрирования, главной областью их применения
являются все же приложения баз данных. Эти процедуры могут
вызываться из прикладных программ, написанных на таких языках,
как Java, C#, C++, Python и т. д., а также из веб-сценариев, написанных на JavaScript и подобных языках. Кроме того, эти процедуры
можно вызывать в интерактивном режиме из командной оболочки
psql.
Выделяют следующие преимущества хранимых процедур:
• Большая безопасность.
• Меньший сетевой трафик.
• SQL-код можно оптимизировать.
• Совместное использование кода между разработчиками.
В отличие от кода приложений, хранимые процедуры никогда
не передаются на клиентские компьютеры. Она всегда находятся в
базе данных и выполняются СУБД на том компьютере, где располагается сервер базы данных. Таким образом, они более безопасны,
чем распространяемый код приложения, а кроме того, снижают
сетевой трафик. Хранимые процедуры постепенно становятся предпочтительным режимом реализации логики приложения в сети Интернет и корпоративных интрасетях. Еще одно преимущество хранимых процедур заключается в том, что SQL-запросы в них могут
быть оптимизированы компилятором СУБД.
Пример хранимой процедуры
Предположим, для нашего примера требуется возможность
добавлять в базу данных сведения о новых клиентах и о том, какими
художниками они интересуются. В частности, нужно записывать
имя и телефон клиента, а также связывать его со всеми художниками выбранной национальности.
78

Глава 4. Применение SQL 4.3. Хранимые процедуры
В листинге 4.1 представлена хранимая процедура, выполняющая эту задачу. Процедура, которая называется customer_insert,
принимает четыре параметра: newname (имя нового клиента),
newareacode (код региона), newphone (телефон) и artistnationality
(национальность художника). Ключевое слово IN указывает на то,
что все эти параметры являются входными. Выходные параметры
(которых у этой процедуры нет) обозначаются ключевым словом
OUT, а параметры, играющие роль и входных и выходных, – соче-
танием INOUT. Следует обратить внимание, что для параметра указывается только тип данных, а длина не указывается. PostgreSQL
определит длину из контекста.
Листинг 4.1.
CREATE OR REPLACE FUNCTION customer_insert(
newname IN char,
newareacode IN char,
newphone IN char,
artistnationality IN char)
RETURNS int AS $customer_insert$
DECLARE
artistcursor CURSOR FOR
SELECT ArtistID
FROM ARTIST
WHERE Nationality = artistnationality;
rowcount int;
BEGIN
SELECT Count(*) INTO rowcount
FROM CUSTOMER
WHERE Name = newname
AND AreaCode = newareacode
AND PhoneNumber = newphone;
IF rowcount > 0 THEN
RAISE EXCEPTION ’There is client in DB! Count is %!’,
rowcount;
END IF;
INSERT INTO CUSTOMER
(CustomerID, Name, AreaCode, PhoneNumber)
VALUES (nextval(’seq_customer’), newname,
newareacode, newphone);
79

4.3. Хранимые процедуры Глава 4. Применение SQL
FOR artist IN artistcursor LOOP
INSERT INTO CUSTOMER_ARTIST_INT
(CustomerID, ArtistID)
VALUES (currval(’seq_customer’), artist.ArtistID);
RAISE INFO ’Artist %; Customer %’,
currval(’seq_customer’), artist.ArtistID;
END LOOP;
RAISE INFO ’Client is added!’;
RETURN 1;
END;
$customer_insert$ LANGUAGE plpgsql;
Раздел объявления переменных следует за ключевым словом
DECLARE. Оператор SELECT определяет переменную-курсор (cursor
variable) с именем artistcursor. Этот курсор выделяет из таблицы
ARTIST для обработки строки всех художников заданной националь-
ности.
В первой части процедуры проверяется, есть ли в базе информация о данном клиенте. В этом случае никакие действия не
предпринимаются, а пользователю с помощью оператора RAISE выводится соответствующее сообщение. Следует обратить внимание,
что для вывода строки и значения переменной используется следующий синтаксис:
RAISE уровень<> строка’<> %’ переменная<>;
В данном случае в качестве уровня могут быть указаны следующие значения: DEBUG, LOG, INFO, NOTICE, WARNING и EXCEPTION. Уровень
EXCEPTION используется по-умолчанию. При использовании уровня
EXCEPTION вызывается исключение, завершающее текущую тран-
закцию с выводом сообщения об ошибке, остальные уровни лишь
выводят сообщения с различным уровнем приоритета. Символ ’%’
используется для вставки в строку значения переменной.
Пользователь получит это сообщение только в том случае, если процедура будет вызвана из psql или pgAdmin III. В случае вызова
процедуры иным путем, например с помощью браузера через Интернет, пользователь не увидит этого сообщения. Чтобы сообщить
80
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
