16. Представления (VIEW)
Представление (view) — это объект базы данных, хранящийся в области метаданных. Другое название для представления,
которое можно встретить в литературе: просмотр, обзор. Представление — виртуальная (реально не существующая) таблица,
которая в базе данных не хранится. Основой представления является оператор SELECT произвольной сложности,
который задает выборку данных из одной или более таблиц, других представлений, а также селективных хранимых процедур.
В базе данных хранится оператор SELECT, но не результаты его выполнения. Результат в виде набора данных создается
при обращении к представлению. К представлениям можно обращаться в операторах SELECT, представления могут принимать
участие в операциях объединения (UNION) и соединения (JOIN), заданных в операторе выборки данных.
Представления, задавая выборку не всех, а только отдельных столбцов и строк исходных таблиц, дают возможность скрыть от рядового пользователя системы некоторые данные, не предназначенные для широкого просмотра. Например, это могут быть оклады сотрудников, пароли, некоторые количественные характеристики деятельности организации и др. В этом отношении представления являются хорошим средством повышения безопасности данных.
16.1. Создание представлений
Для создания представления используется оператор CREATE VIEW.
Синтаксис оператора показан в листинге .
Листинг 16.1 Синтаксис оператора создания представления CREATE VIEW
CREATE VIEW <имя представления> [<список столбцов>]
AS <оператор SELECT>
[WITH CHECK OPTION]
<список столбцов> ::= ( <столбец> [, <столбец> ...])
Примечание
Представления могут создаваться администраторами и пользователями с привилегией CREATE VIEW.
Для создания представления пользователями, которые не имеют административных привилегий,
необходимы также привилегии на чтение (SELECT) данных из базовых таблиц и представлений,
и привилегии на выполнение (EXECUTE) используемых селективных хранимых процедур.
Для разрешения вставки, обновления и удаления через представление, необходимо чтобы создатель
(владелец) представления имел привилегии INSERT, UPDATE и DELETE на базовые объекты метаданных.
Пользователь, создавший представление, становится его владельцем.
Имя представления должно быть уникальным среди имен всех представлений, таблиц и хранимых процедур базы данных.
Поля представления
После имени создаваемого представления может идти список имен полей представления, заключенный в скобки.
Если в представлении присутствуют элементы, значения которых получаются из выражений, то такой список
столбцов является обязательным. В остальных случаях список можно не указывать. Обращение к столбцам
можно осуществлять по именам столбцов, которые указаны в списке выбора главного оператора SELECT
в представлении. Однако хорошей практикой является явное задание списка столбцов в самом представлении.
Имена в списке могут быть никак не связаны с именами столбцов базовых таблиц. При этом их количество
должно точно соответствовать количеству столбцов в списке выбора главного оператора SELECT представления.
По этим именам в списке к столбцам полученного набора данных можно обращаться в операторе SELECT,
вызывающем данное представление.
Предложение AS
После ключевого слова AS следует оператор SELECT. Здесь можно выполнять объединение (UNION)
и соединение (JOIN) различных таблиц, использовать предложение WHERE для задания условий выбора
строк. Возможности оператора SELECT см. в главе 12.
Изменяемые представления
Представление может быть изменяемым (в двух вариантах — естественно изменяемым или изменяемым при
помощи вспомогательных триггеров) или неизменяемым, только для чтения (read-only). В случае
естественно изменяемого представления в данные, полученные при помощи такого представления
(в базовую таблицу представления, то есть в таблицу, из которой представление получает все данные),
пользователь может свободно вносить любые изменения, используя операторы
INSERT, UPDATE, DELETE, UPDATE OR INSERT, MERGE. Выполненные изменения тут же помещаются в таблицу.
При неизменяемом представлении пользователь не может вносить обычными средствами изменения в
выбранные данные. Во многих случаях и в неизменяемое представление (в базовые таблицы) можно
вносить изменения при использовании вспомогательных триггеров. Использование триггеров для получения
изменяемых представлений из неизменяемых см. в разделе 16.6 данной главы.
Чтобы представление было естественно изменяемым, необходимо выполнение следующих условий:
оператор
SELECTвыборки данных обращается только к одной таблице или к одному другому изменяемому представлению;оператор выборки
SELECTне должен обращаться к хранимым процедурам;все столбцы исходной (базовой) таблицы или исходного изменяемого представления, которые не присутствуют в данном представлении, должны удовлетворять одному из следующих условий:
позволять значение
NULL;NOT NULLстолбцы должны иметь значение по умолчанию;значение
NOT NULLстолбцов должны быть инициализированы в триггерах базовых таблиц;
оператор выборки
SELECTне содержит полей определённых через подзапросы или другие выражения;оператор выборки
SELECTне содержит полей определённых через агрегатные функции (MIN, MAX, AVGи др.), статистические функции (CORR, COVAR_POP, COVAR_SAMPи др.), функции линейной регрессии (REGR_AVGX, REGR_AVGYи др.) и все виды оконных функций;оператор выборки
SELECTне содержит предложенийORDER BY, GROUP BY, HAVING;оператор выборки
SELECTне содержит ключевого словаDISTINCTи ограничений количества строкROWS, FIRST, SKIP, OFFSET, FETCH.
Предложение WITH CHECK OPTION
Необязательное предложение WITH CHECK OPTION задает для изменяемого представления требование
проверки соответствия вновь вводимых или изменяемых данных условию, заданному в предложении WHERE.
Если будет попытка поместить новую строку, которая не соответствует условию выборки в предложении WHERE,
то такая строка не помещается в таблицу, выдается соответствующее диагностическое сообщение. Точно так же
в этом случае недопустимы операции изменения полученных из представления данных, которые приводят к
нарушению условия выборки в предложении WHERE.
Предложение WITH CHECK OPTION может задаваться в операторе создания представления только в
том случае, если в операторе SELECT представления указано предложение WHERE.
Иначе вы получите сообщение об ошибке.
Примечание
Если используется предложение WITH CHECK OPTIONS, то система проверяет входные значение на
соответствие условию в предложении WHERE до того как они будут переданы в базовую таблицу.
Таким образом, если входные значения не проходят проверку, то предложения DEFAULT или
триггеры на базовой таблице, не могут исправить входные значения, поскольку действия никогда не будут выполнены.
Кроме того, поля представления не указанные в операторе INSERT передаются в базовую
таблицу как значения NULL, независимо от их наличия или отсутствия в предложении WHERE.
В результате значения по умолчанию, определённые на таких полях базовой таблицы, не будут
применены. С другой стороны, триггеры будут вызываться и работать как ожидалось.
Примечание
Для представлений у которых отсутствует предложение WITH CHECK OPTIONS, поля, отсутствующие в
операторе INSERT, не передаются вовсе, поэтому любые значения по умолчанию будут применены.
16.2. Изменение представлений
Для изменения существующего представления используется оператор ALTER VIEW. Синтаксис оператора
показан в листинге .
Листинг 16.2 Синтаксис оператора создания представления ALTER VIEW
ALTER VIEW <имя представления> [<список столбцов>]
AS <оператор SELECT>
[WITH CHECK OPTION]
<список столбцов> ::= (столбец [, столбец ...])
Оператор ALTER VIEW изменяет определение существующего представления, существующие
права на представления и зависимости при этом сохраняются. Синтаксис оператора ALTER VIEW
полностью аналогичен синтаксису оператора CREATE VIEW.
Примечание
Изменить представление могут только владелец представления, администратор, пользователь с привилегией ALTER ANY VIEW.
Предупреждение
Будьте осторожны при изменении количества столбцов представления. Существующий код приложения может стать неработоспособным. Кроме того, PSQL модули, использующие изменённое представление, могут стать некорректными. Информация о том, как это обнаружить, находится в разделе 31.46.
16.3. Создание или изменение представлений
Для создание нового или изменение существующего представления используется оператор
CREATE OR ALTER VIEW. Синтаксис оператора показан в листинге .
Листинг 16.3 Синтаксис оператора создания представления CREATE OR ALTER VIEW
CREATE OR ALTER VIEW <имя представления> [<список столбцов>]
AS <оператор SELECT>
[WITH CHECK OPTION]
<список столбцов> ::= (столбец [, столбец ...])
Оператор CREATE OR ALTER VIEW создаёт представление, если оно не существует.
В противном случае он изменит представление с сохранением существующих зависимостей.
16.4. Удаление представлений
Для удаления существующего в базе данных представления используется оператор DROP VIEW.
Его синтаксис представлен в листинге .
Листинг 16.4 Синтаксис оператора удаления представления DROP VIEW
DROP VIEW <имя представления>;
Представление нельзя удалить, если на него есть ссылки в другом представлении, в
хранимой процедуре или в ограничении CHECK столбца таблицы или соответствующего
ограничения на уровне таблицы.
Примечание
Удалить представление может только владелец представления, администратор, пользователь с привилегией DROP ANY VIEW.
16.5. Пересоздание представлений
Оператор RECREATE VIEW позволяет внести изменения в существующее представление.
Листинг 16.5 Синтаксис оператора пересоздания представления RECREATE VIEW
RECREATE VIEW <имя представления> [<список столбцов>]
AS <оператор SELECT>
[WITH CHECK OPTION]
<список столбцов> ::= (столбец [, столбец ...])
Представление может отсутствовать в базе данных. В этом случае оно просто создается заново.
Если представление с этим именем уже существует в базе данных, то оно удаляется и затем
создается заново. Попытка выполнить пересоздание представления приведет к ошибке базы данных,
если это представление в настоящий момент находится в использовании. Оператор RECREATE VIEW
не выполнится, если существующее представление имеет зависимости.
16.6. Примеры представлений
Любой пример оператора SELECT из главы 12 можно записать в виде представления.
В одном из примеров главы 12 был приведен пример использования производной таблицы.
Можно создать соответствующее представление USER_TABLES. Это представление отображает
все пользовательские таблицы базы данных.
CREATE VIEW USER_TABLES
(RDB$RELATION_NAME, RDB$RELATION_ID)
AS
SELECT *
FROM (SELECT
RDB$RELATION_NAME,
RDB$RELATION_ID
FROM RDB$RELATIONS
WHERE RDB$RELATION_NAME NOT STARTING WITH 'RDB$')
AS R ("Таблица", "Идентификатор");
Здесь выбираются таблицы, чьи имена не начинаются с символов 'RDB$', то есть таблицы, не
являющиеся системными. В этом представлении должны быть обязательно
указаны имена столбцов после имени представления. В примере заданы те
же имена столбцов, что и в операторе SELECT. Фактически имена могут
быть любыми. Эти имена можно использовать в операторе SELECT, который
обращается к данному представлению. Оператор, выполняющий данное представление:
SELECT RDB$RELATION_NAME, RDB$RELATION_ID
FROM USER_TABLES;
Во многих случаях представление бывает особенно полезным тогда, когда оператор выборки
данных SELECT является довольно сложным. Использование представлений позволит сократить
объем ручного ввода пользователем и уменьшить вероятность ошибок.
Можно составить представление для получения списка людей и их родителей, что было показано
в операторе SELECT в примере в главе 12.
Соответствующий оператор SELECT представления также содержит два левых внешних соединения с той же таблицей.
CREATE VIEW SELECT_PEOPLE (C1, C2, C3)
AS
SELECT
PG.FULLNAME AS "Фамилия, имя, отчество",
PM.NAME3 AS "Мать",
PF.NAME3 AS "Отец"
FROM PEOPLE PG /* Главная таблица */
LEFT OUTER JOIN PEOPLE PM /* Мать */
ON PG.CODMOTHER = PM.COD
LEFT OUTER JOIN PEOPLE PF /* Отец */
ON PG.CODFATHER = PF.COD;
Это представление не является естественно изменяемым, поскольку список выбора не содержит столбец код
человека, а этот столбец, являясь первичным ключом таблицы, не допускает пустого значения NULL.
По этой причине такое представление вообще не может быть сделано изменяемым даже и при помощи триггеров
(см. далее в разделе 16.7 этой главы).
Кроме того, в представлении выполняется соединение таблиц (для определения, является ли представление
естественно изменяемым, неважно, что таблица соединяется сама с собой; проблема не в том, что при изменении
затрагивается не одна, а несколько таблиц, а в том, что изменение происходит для нескольких строк).
Попытки выполнить добавление новых данных, изменение или удаление существующих строк приведут к выдаче
диагностического сообщения о попытке изменять представление только для чтения (read-only).
Список имен столбцов в самом представлении (C1, C2, C3) никак не связан с именами столбцов,
получаемых из базовых таблиц, что вполне допустимо.
Для выборки данных при помощи этого представления можно использовать, например,
следующий оператор SELECT:
SELECT
C1 AS "Фамилия, имя, отчество",
C2 AS "Мать",
C3 AS "Отец"
FROM SELECT_PEOPLE
ORDER BY C1;
Следующий несколько надуманный пример демонстрирует использование предложения WITH CHECK OPTION.
Представление является естественно изменяемым, потому что данные выбираются из одной таблицы, и
единственный столбец, который не допускает пустого значения NULL (первичный ключ, код страны — CODCOUNTRY)
включен в список выбора.
CREATE VIEW V_TEST (CODCOUNTRY, NAME, FULLNAME, CAPITAL, DESCR)
AS
SELECT *
FROM COUNTRY
WHERE CODCOUNTRY CONTAINING 'A'
WITH CHECK OPTION;
Здесь выбираются все страны из таблицы стран, у которых в коде страны присутствует символ «A» —
неважно, в начале, в середине или в конце строки. Предложение WITH CHECK OPTION задает такое условие,
что пользователь не может добавить новую запись в полученный набор данных или изменить код страны
существующей записи, если не будет выполняться условие в предложении WHERE, то есть, если код
страны не будет содержать символа «A».
В следующем простом представлении выбираются все регионы всех стран, хранящиеся в базе данных.
CREATE VIEW V_REGION (CODCOUNTRY, CODREGION, NAMEREG, CENTER, DESCR)
AS
SELECT * FROM REGION;
Это представление является естественно изменяемым. Для него можно выполнять операторы добавления, изменения и удаления существующих данных, как если бы это представление было обычной таблицей. Нет необходимости в написании триггеров для внесения изменений в базовую таблицу.
С таблицей, получаемой при обращении с помощью оператора SELECT к представлению, можно
выполнять все действия, как и с обычной таблицей. В частности, можно выполнить соединение
полученной при обращении к представлению таблицы с другой таблицей базы данных. Следующий
оператор SELECT, при обращении к только что описанному представлению, выполняет соединение
каждой строки из списка регионов со справочником стран, добавляя в результирующий набор данных
краткое и полное название страны, к которой относится выбираемый в операторе регион:
SELECT
V_REGION.*,
COUNTRY.NAME,
COUNTRY.FULLNAME
FROM V_REGION
LEFT OUTER JOIN COUNTRY
ON V_REGION.CODCOUNTRY = COUNTRY.CODCOUNTRY
ORDER BY 1;
Можно создать естественно изменяемое представление VIEW_RUSSIA2, которое выбирает все регионы России.
Оператор создания такого представления показан в следующем примере. Здесь код страны 'РОССИЯ' получается
при помощи внутреннего оператора SELECT, который получает код на основании заданного краткого названия страны.
CREATE VIEW VIEW_RUSSIA2 (CODCOUNTRY, CODREGION, NAMEREG, CENTER)
AS
SELECT
CODCOUNTRY, CODREGION, NAMEREG, CENTER
FROM REGION
WHERE CODCOUNTRY = (SELECT CODCOUNTRY
FROM COUNTRY
WHERE NAME = 'Россия');
Просмотреть регионы с использованием данного представления можно обычным оператором SELECT:
SELECT
CODCOUNTRY AS "Код страны",
CODREGION AS "Код региона",
NAMEREG AS "Название региона",
CENTER AS "Центр региона"
FROM VIEW_RUSSIA2;
При использовании этого представления можно изменить значение любого столбца базовой таблицы (изменять можно значения только тех столбцов, которые явно описаны в этом представлении). Например, можно изменить название региона:
UPDATE VIEW_RUSSIA2
SET NAMEREG = 'Неизвестная область'
WHERE CODREGION = '64' AND
CODCOUNTRY = (SELECT CODCOUNTRY
FROM COUNTRY
WHERE NAME = 'Россия');
Разумеется, при использовании данного представления можно изменять и код региона, и название центра региона. Здесь можно также изменить и код страны, однако с учетом условия выборки данных регионов при помощи данного представления, такая строка не будет отображена при дальнейшем обращении к этому представлению.
Используя данное представление, можно добавить новый регион. При этом обязательно нужно указать значения всех столбцов, входящих в состав первичного ключа, несмотря на то, что в представлении как бы уже неявно задано условие, что значением кода страны является код России.
INSERT INTO VIEW_RUSSIA2 (CODCOUNTRY, CODREGION, NAMEREG)
VALUES ((SELECT CODCOUNTRY
FROM COUNTRY
WHERE NAME = 'Россия'), '00', 'Несуществующий регион');
Используя данное естественно изменяемое представление, можно удалять строки из базовой таблицы. Здесь удаляется строка, помещенная в таблицу в предыдущем примере.
DELETE FROM VIEW_RUSSIA2
WHERE CODREGION = '00' AND
CODCOUNTRY = (SELECT CODCOUNTRY
FROM COUNTRY
WHERE NAME = 'Россия');
16.7. Преобразование неизменяемых представлений в изменяемые при помощи триггеров
Как уже было сказано, многие представления, являющиеся неизменяемыми (read-only), могут быть сделаны
изменяемыми при создании соответствующих триггеров. Такое преобразование возможно только в том случае,
если все столбцы, не находящиеся в списке выбора при выполнении обращения к данному представлению,
могут принимать пустое значение NULL. Иными словами, все столбцы, входящие в состав первичного
ключа, и все остальные столбцы, для которых явно задано условие NOT NULL, должны присутствовать
в списке выбора оператора SELECT в представлении.
Для того чтобы при использовании представления можно было выполнять оператор добавления данных
(INSERT), необходимо для этого представления написать триггер, выполняемый до добавления
(BEFORE INSERT). Чтобы к представлению можно было применять операцию изменения данных,
необходим триггер BEFORE UPDATE, операцию удаления — триггер BEFORE DELETE.
Предупреждение
Если представление является естественно изменяемым и для него созданы соответствующие триггеры, то любая операция изменения не будет выполнять прямые изменения в таблице. Все изменения будут выполняться только в триггерах. Если триггеры фактически не содержат операторов DML по изменению данных в таблице, то никакие изменения не будут произведены.
Следующий пример создает представление V_REGION_COUNTRY, которое не является естественно изменяемым,
потому что содержит соединение (JOIN) двух таблиц. При этом представление включает в себя все столбцы
базовых таблиц, которые не могут принимать пустые значения. Следовательно, существует принципиальная
возможность сделать это представление изменяемым.
CREATE VIEW V_REGION_COUNTRY
(CODCOUNTRY, CODREGION, NAMEREG, CENTER, DESCR, NAME, FULLNAME)
AS
SELECT
REGION.CODCOUNTRY,
CODREGION,
NAMEREG,
CENTER,
REGION.DESCR,
COUNTRY.NAME,
COUNTRY.FULLNAME
FROM REGION
LEFT OUTER JOIN COUNTRY
ON REGION.CODCOUNTRY = COUNTRY.CODCOUNTRY;
В этом представлении отыскиваются все регионы всех стран, выбираются все
столбцы из таблицы регионов и для каждой строки добавляется краткое
(NAME) и полное (FULLNAME) название соответствующей страны.
Это представление не является естественно изменяемым, для него нельзя
без дополнительных действий использовать операторы INSERT, UPDATE или
DELETE. Поскольку это представление включает в себя все столбцы,
которые не могут иметь пустого значения NULL, то такое представление
легко можно сделать изменяемым, создав для него соответствующие
вспомогательные триггеры. Все триггеры должны выполняться до (BEFORE)
соответствующего действия — добавления, изменения, удаления.
Чтобы предоставить пользователю системы возможность добавлять в базовые
таблицы этого представления новые строки, необходимо для представления
создать только лишь триггер, который будет вызываться до добавления
строки (BEFORE INSERT). При наличии такого триггера можно добавлять
новые строки в базовые таблицы, но при наличии только этого триггера
выполнять иные действия по изменению и удалению будет невозможно.
Примечание
Будет ли на самом деле реально добавлена новая строка в одну таблицу или
несколько строк в обе (во все, используемые в операторе SELECT) базовые
таблицы при использовании для этого представления оператора INSERT
зависит от того, какой код содержится в самом триггере. В триггере
может быть задано добавление новых строк в обе (во все) или только в
одну базовую таблицу. Триггер также может вообще не содержать
операторов добавления новых строк. При этом в случае наличия
соответствующего триггера для данного представления выполнение
оператора INSERT для такого представления не вызовет исключения или
ошибок базы данных (поскольку просто лишь существует подходящий триггер
BEFORE INSERT). Пример такого триггера для представления
V_REGION_COUNTRY приведен в ниже. У пользователя,
выполняющего такой оператор INSERT, может сложиться впечатление, что
все действия привели к нужным ему результатам, что не всегда
соответствует действительности. Это может стать хорошим источником
всевозможных ошибок.
SET TERM ^;
CREATE TRIGGER TBI_REGION_COUNTRY
FOR V_REGION_COUNTRY
BEFORE INSERT
AS
BEGIN
END ^
Чтобы дать еще и возможность при использовании описанного представления
выполнять также и изменения в одной из базовых таблиц, а именно
внесение изменений в справочник регионов REGION, нужно создать триггер,
который будет выполняться до изменения (BEFORE UPDATE) этого представления.
SET TERM ^;
CREATE TRIGGER TBU_REGION_COUNTRY
FOR V_REGION_COUNTRY
BEFORE UPDATE
AS
BEGIN
UPDATE REGION
SET NAMEREG = NEW.NAMEREG
WHERE CODCOUNTRY = OLD.CODCOUNTRY AND CODREGION = OLD.CODREGION;
END ^
Этот триггер позволяет изменять только название региона и только в таблице регионов. Другие столбцы этой таблицы, а также любые столбцы соединяемой родительской таблицы стран изменяться не будут. Например, следующий оператор будет выполнен и выполнен правильно.
UPDATE V_REGION_COUNTRY
SET NAMEREG = 'Another region'
WHERE CODREGION = '64';
Следующий оператор также не вызовет никаких сообщений об ошибках, однако его выполнение не приведет ни к каким изменениям в базовых таблицах.
UPDATE V_REGION_COUNTRY
SET FULLNAME = 'Еще одна страна'
WHERE CODREGION = '64';
Здесь предполагается, что должно быть изменено полное название страны в таблице стран, которая является родительской для указанной строки регионов. Однако, поскольку такое изменение никак не описано в триггере, то никакие действия по модификации данных выполнены не будут.
Следующий триггер выполняет удаление заданных строк из обеих базовых таблиц — как из таблицы регионов,
так и из таблицы стран. Триггер должен выполняться до удаления (BEFORE DELETE) данного представления.
SET TERM ^;
CREATE TRIGGER TBD_REGION_COUNTRY
FOR V_REGION_COUNTRY
BEFORE DELETE
AS
BEGIN
DELETE FROM REGION
WHERE CODCOUNTRY = OLD.CODCOUNTRY AND CODREGION = OLD.CODREGION;
DELETE FROM COUNTRY
WHERE CODCOUNTRY = OLD.CODCOUNTRY;
END ^
Следующий оператор выполняет удаление заданных строк в обеих базовых таблицах:
DELETE FROM V_REGION_COUNTRY
WHERE CODCOUNTRY = 'USA';
Примечание
Вообще говоря, удаление в данном триггере не только страны, но еще и региона явно является излишним,
так как удаление заданной строки страны автоматически приведет к удалению всех регионов этой страны
(если в описании внешнего ключа в дочерней таблице регионов задано ON DELETE CASCADE).
Вместо написания трех триггеров можно создать один для всех обновляющих действий фазы BEFORE.
Пример триггера, объединяющего все функции предыдущих триггеров:
SET TERM ^;
CREATE TRIGGER TBC_REGION_COUNTRY
FOR V_REGION_COUNTRY
BEFORE UPDATE OR INSERT OR DELETE
AS BEGIN
IF (UPDATING) THEN
BEGIN
UPDATE REGION
SET NAMEREG = NEW.NAMEREG
WHERE CODCOUNTRY = OLD.CODCOUNTRY AND CODREGION = OLD.CODREGION;
END
IF (INSERTING) THEN
BEGIN
END
IF (DELETING) THEN
BEGIN
DELETE FROM REGION
WHERE CODCOUNTRY = OLD.CODCOUNTRY AND CODREGION = OLD.CODREGION;
DELETE FROM COUNTRY
WHERE CODCOUNTRY = OLD.CODCOUNTRY;
END
END ^
В этом триггере объединяется функциональность трех предыдущих триггеров,
относящихся к представлению V_REGION_COUNTRY.
С целью определения, для какой обновляющей операции вызывается триггер,
используются контекстные переменные UPDATING, INSERTING и DELETING.
Подробнее о контекстных переменных см. в главе 21. В этом триггере также не
осуществляется никаких действий по добавлению данных, однако выполнение оператора
INSERT для представления V_REGION_COUNTRY не вызовет ошибок.
Предупреждение
Если и для базовых таблиц представления также заданы соответствующие триггеры
для фаз BEFORE, то выполнение триггеров для представления происходит прежде,
чем выполнение этих триггеров для базовых таблиц. Это нужно учитывать, в частности
и при формировании значения искусственного первичного ключа, которое выбирается из
генератора (GENERATOR, SEQUENCE).
Преобразование неизменяемых представлений в изменяемые при помощи триггеров требует особой, повышенной осторожности.
Подробности о языке хранимых процедур и триггеров (PSQL), о создании, удалении и изменении триггеров см. в главе 18 и главе 21.
16.8. Системные представления
В стандарте SQL-92 определены представления для отображения системных сведений об ограничениях целостности в базе данных. Здесь приведено четыре полезных системных представления.
Представление CHECK_CONSTRAINTS, показанное в следующем примере, позволяет получить список всех
ограничений базы данных — ограничений первичного, уникального, внешнего ключей и ограничений CHECK.
В случае ограничения CHECK вторым столбцом выводится текст условия ограничения.
CREATE VIEW CHECK_CONSTRAINTS (CONSTRAINT_NAME, CHECK_CLAUSE)
AS
SELECT RDB$CONSTRAINT_NAME, RDB$TRIGGER_SOURCE
FROM RDB$CHECK_CONSTRAINTS RC, RDB$TRIGGERS RT
WHERE RT.RDB$TRIGGER_NAME = RC.RDB$TRIGGER_NAME;
Для обращения к этому представлению можно использовать, например, такой
оператор SELECT:
SELECT
CONSTRAINT_NAME AS "Имя ограничения",
CHECK_CLAUSE AS "Предложение CHECK"
FROM CHECK_CONSTRAINTS;
Представление CONSTRAINTS_COLUMN_USAGE выводит список всех таблиц базы данных, их столбцов и
ограничений, применяющихся для соответствующих столбцов. Здесь отображаются только сведения о
первичных, уникальных и внешних ключах. Ограничения CHECK в этом списке отсутствуют.
CREATE VIEW CONSTRAINTS_COLUMN_USAGE
(TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME)
AS
SELECT
RDB$RELATION_NAME,
RDB$FIELD_NAME,
RDB$CONSTRAINT_NAME
FROM RDB$RELATION_CONSTRAINTS RC, RDB$INDEX_SEGMENTS RI
WHERE RI.RDB$INDEX_NAME = RC.RDB$INDEX_NAME;
Получить соответствующий список можно, выполнив, например, следующий
оператор SELECT:
SELECT
TABLE_NAME AS "Таблица",
COLUMN_NAME AS "Столбец",
CONSTRAINT_NAME AS "Имя ограничения"
FROM CONSTRAINTS_COLUMN_USAGE;
В следующем примере показано системное представление, отображающее список всех внешних ключей в базе данных.
В каждой строке в первом столбце содержится имя таблицы, затем имя внешнего ключа, после этого имя
первичного или уникального ключа, на который ссылается данный внешний ключ, потом уровень соответствия
(в данной версии всегда FULL — полное соответствие внешнего ключа ключу родительской таблицы; будет
использовано в дальнейших версиях), поведение системы при изменении значения (ON UPDATE) ключевого
реквизита родительской таблицы и при удалении строки (ON DELETE) родительской таблицы.
CREATE VIEW REFERENTIAL_CONSTRAINTS
(CONSTRAINT_NAME, UNIQUE_CONSTRAINT_NAME, MATCH_OPTION,
UPDATE_RULE, DELETE_RULE)
AS
SELECT
RDB$CONSTRAINT_NAME,
RDB$CONST_NAME_UQ,
RDB$MATCH_OPTION,
RDB$UPDATE_RULE,
RDB$DELETE_RULE
FROM RDB$REF_CONSTRAINTS;
Для получения списка ограничений внешнего ключа базы данных можно
использовать следующий оператор SELECT:
SELECT
CONSTRAINT_NAME AS "Внешний ключ",
UNIQUE_CONSTRAINT_NAME AS "Первичный/уникальный ключ",
MATCH_OPTION AS "Уровень соответствия",
UPDATE_RULE AS "ON UPDATE",
DELETE_RULE AS "ON DELETE"
FROM REFERENTIAL_CONSTRAINTS;
Представление TABLE_CONSTRAINTS позволяет получить список всех ограничений всех таблиц.
Сюда входят ограничения первичного, уникального, внешнего ключей, ограничение CHECK и
ограничение NOT NULL. Каждая строка содержит имя ограничения (имя, заданное пользователем
при описании ограничения, или имя, сгенерированное системой, если пользователь не задал никакого
имени), имя таблицы, для которой создано ограничение, и вид ограничения. Последние два символьных
столбца, указанные в этом представлении (IS_DEFERRABLE и INITIALLY_DEFERRED), во всех
строках содержат текст "NO", они будут использованы в дальнейших расширениях системы.
CREATE VIEW TABLE_CONSTRAINTS
(CONSTRAINT_NAME, TABLE_NAME, CONSTRAINT_TYPE,
IS_DEFERRABLE, INITIALLY_DEFERRED)
AS
SELECT
RDB$CONSTRAINT_NAME,
RDB$RELATION_NAME,
RDB$CONSTRAINT_TYPE,
RDB$DEFERRABLE,
RDB$INITIALLY_DEFERRED
FROM RDB$RELATION_CONSTRAINTS;
Обращение к этому представлению может быть выполнено следующим
оператором SELECT:
SELECT
CONSTRAINT_NAME AS "Имя ограничения",
TABLE_NAME AS "Таблица",
CONSTRAINT_TYPE AS "Вид ограничения",
IS_DEFERRABLE,
INITIALLY_DEFERRED
FROM TABLE_CONSTRAINTS;
16.9. Примечание представления
Для представления можно создать примечание, используя следующий синтаксис оператора COMMENT:
Листинг 16.6 Синтаксис оператора примечания представления COMMENT ON VIEW
COMMENT ON VIEW <имя представления> IS {'<текст>' | NULL};
Если в качестве текста примечания задать NULL, то будет удалено существующее примечание представления.
Чтобы добавить примечание к представлению V_REGION, нужно выполнить оператор:
COMMENT ON VIEW V_REGION IS 'Выбор всех регионов всех стран';