Все изменения в
метаданных, относящихся к таблицам, фиксируются InterBase сервером. И эта
информация находится в таблицах rdb$relations и RDB$FORMATS. В таблице
RDB$FORMATS есть счетчик изменений, но он ограничен количеством 256. Когда
счетчик достигнет этого значения, то дальнейшие изменения метаданных будут
невозможны, пока не будет выполнена операция backup/restore. Модифицируем
предыдущий запрос: select a.RDB$RELATION_NAME,a.RDB$FIELD_ID,a.RDB$OWNER_NAME, Max(b.RDB$FORMAT)
from RDB$RELATIONS a, RDB$FORMATS b
where a.RDB$RELATION_ID = b.RDB$RELATION_ID and a.RDB$SYSTEM_FLAG = 0
and (a.rdb$view_source is null)
group by a.RDB$RELATION_NAME, a.RDB$FIELD_ID, a.RDB$OWNER_NAME
order by 4 desc;
Последний столбец будет содержать максимальное значение этого счетчика для
каждой таблицы. select a.rdb$field_name, a.rdb$field_position, a.rdb$null_flag,
a.rdb$field_source, a.rdb$default_source, b.rdb$computed_source,
b.rdb$field_length, b.rdb$field_scale, b.rdb$field_type, B.rdb$field_sub_type
from rdb$relation_fields a, rdb$fields b
where a.rdb$field_source = b.rdb$field_name and A.rdb$relation_name = "EMPLOYEE"
order by a.rdb$field_position asc;
Приведенный выше запрос возвращает структуру конкретной таблицы EMPLOYEE.
Выбранные поля имеют следующую смысловую нагрузку:
rdb$field_name |
Имя поля, должно быть уникальное для таблицы. |
rdb$field_position |
Позиция поля в структуре таблицы. |
rdb$null_flag |
Определяет, может ли поле содержать NULL значение. 1 - не может. |
rdb$field_source |
Имя псевдонима типа, на котором основано это поле. |
rdb$default_source |
Содержит значение по умолчанию для этого поля. |
rdb$computed_source |
Содержит выражение для вычисления значения поля. |
rdb$field_length |
Длина поля. |
rdb$field_scale |
Масштаб числовых типов данных. |
rdb$field_type |
Тип поля. |
rdb$field_sub_type |
Подтип поля, для уточнения типа BLOB полей. |
Нужно заметить, что тип поля будет представлен в виде числа.
Это удобно для дальнейшего программного анализа, но совсем не наглядно.
Информация о всевозможных типах, в том числе и о типах полей, содержится в
таблице RDB$TYPES. Попробуем модифицировать запрос: select a.rdb$field_name, a.rdb$field_position, a.rdb$null_flag,
a.rdb$field_source, a.rdb$default_source, b.rdb$computed_source,
b.rdb$field_length, b.rdb$field_scale, c.RDB$TYPE_NAME, B.rdb$field_sub_type
from rdb$relation_fields a, rdb$fields b, RDB$TYPES c
where (a.rdb$field_source = b.rdb$field_name) and (b.RDB$FIELD_TYPE = c.rdb$type)
and (c.RDB$FIELD_NAME = "RDB$FIELD_TYPE")
and (a.rdb$relation_name = "EMPLOYEE")
order by a.rdb$field_position asc;
Здесь тип поля будет представлен текстовой строкой.
Псевдонимы типов - это достаточно мощный механизм, позволяющий
описать свойства будущих полей. Создав псевдоним типа, Вы в дальнейшем будете
использовать его при создании таблиц, таким образом, упростив запись предложения
CREATE TABLE при создании таблицы и сделав его более наглядным. Следующий SQL
запрос покажет список псевдонимов, созданных пользователем, которые были
использованы при создании таблицы. select rdb$field_source
from rdb$relation_fields
where (rdb$relation_name = "EMPLOYEE")
and not (rdb$field_source STARTING WITH "RDB$");
Ограничения.
Поговорим немного об ограничениях, которые Вы накладываете на
таблицы, что бы они удовлетворяли условиям ссылочной целостности или содержали в
полях значения, удовлетворяющие определенным правилам. Одно такое ограничение
уже упоминалось. Это поле rdb$null_flag из таблицы rdb$relation_fields, которое
информирует Вас о том, может ли столбец таблицы содержать значение NULL. select RDB$CONSTRAINT_NAME, RDB$CONSTRAINT_TYPE, RDB$INDEX_NAME
from rdb$relation_constraints
where rdb$relation_name = quot;EMPLOYEE";
Этот запрос возвращает информацию почти обо всех ограничениях,
наложенных на таблицу. Поле RDB$CONSTRAINT_NAME - это имя ограничения.
RDB$INDEX_NAME - имя индекса для ограничений типа UNIQUE, PRIMARY KEY и FOREIGN
KEY. Достаточно легко получить список ограничений определенного типа, например: SELECT RDB$CONSTRAINT_NAME
FROM RDB$RELATION_CONSTRAINTS
WHERE (RDB$RELATION_NAME = "EMPLOYEE") and (rdb$constraint_type = "CHECK");
Этот запрос выдает список имен CHECK ограничений. Рассмотрим подробнее каждый
тип ограничения.
CHECK ограничения базируются на триггерах. Эти триггеры
создаются InterBase сервером автоматически при создании соответствующего CHECK
ограничения. Однако можно посмотреть, какие триггеры работают при обработке
ограничения. select rdb$trigger_name
from rdb$check_constraints
where rdb$constraint_name = "INTEG_30";
В условии отбора указывается имя ограничения, полученное предыдущим SQL
запросом. Нужно заметить, что для ограничений этого типа создается два триггера
типа BEFORE INSERT и BEFORE UPDATE.
О том, как получить информацию о триггерах, мы поговорим ниже.
Ограничения типа UNIQUE, PRIMARY KEY и FOREIGN KEY базируются
на индексах, которые также создаются InterBase сервером автоматически. Можно
получить список имен ограничений и соответствующие имена индексов следующим
запросом: SELECT RDB$CONSTRAINT_NAME, RDB$INDEX_NAME
FROM RDB$RELATION_CONSTRAINTS
WHERE (RDB$RELATION_NAME = "EMPLOYEE") AND
(RDB$CONSTRAINT_TYPE = "FOREIGN KEY");
Имея имя индекса, можно просмотреть на базе каких полей построен этот индекс,
активен ли он и т.д. Об этом мы поговорим чуть позже.
Индексы FOREIGN KEY поддерживают ссылочную целостность между
таблицами в базе данных. При помощи их устанавливается связь, и им соответствуют
индексы PRIMARY KEY. Среди служебных таблиц базы данных есть таблица, которая
связывает пары FOREIGN KEY и PRIMARY KEY. Это RDB$INDICES. Учитывая все это
можно определить, с какой таблицей связана данная таблица по выбранному индексу
FOREIGN KEY. Следующий SQL возвращает имя таблицы и индекс PRIMARY KEY, с
которым осуществляет связь индекс FOREIGN KEY. В данном случае это RDB$FOREIGN9.
select rdb$relation_name , rdb$index_name
from rdb$indices where rdb$index_name in
(select rdb$foreign_key
from rdb$indices
where rdb$index_name = "RDB$FOREIGN9");
Учитывая, что таблица RDB$REF_CONSTRAINTS содержит список всех вторичных
ключей с поставленными в соответствие первичными ключами, то можно попробовать
определить пары таблиц master-detail. SELECT a.RDB$RELATION_NAME,a.RDB$INDEX_NAME,
c.RDB$RELATION_NAME, c.RDB$INDEX_NAME
FROM RDB$RELATION_CONSTRAINTS a, RDB$REF_CONSTRAINTS b,
RDB$RELATION_CONSTRAINTS c
WHERE (a.RDB$CONSTRAINT_NAME = b.RDB$CONSTRAINT_NAME)
and (b.RDB$CONST_NAME_UQ = c.RDB$CONSTRAINT_NAME)
order by a.RDB$RELATION_NAME;
Этот SQL-запрос, кроме пар таблиц master-detail, возвращает и
имена соответствующих индексов PRIMARY KEY и FOREIGN KEY. Эти поля можно убрать
и тогда Вы получите просто таблицу связей между таблицами.
Индексы.
Индексы - важный объект базы данных. Как Вы уже видели, они
используются для построения ограничений типа PRIMARY KEY, FOREIGN KEY и UNIQUE.
Но, кроме этих важных индексов, создаваемых SQL сервером автоматически, в базе
данных присутствуют и индексы, созданные пользователем. Они употребляются для
улучшения доступа к данным, обеспечения сортировок.
Несколькими примерами (далеко не исчерпывающими все возможности) я хочу
показать, какую информацию можно почерпнуть из служебных таблиц базы данных
касаемо индексов. select RDB$INDEX_NAME
from rdb$indices
where rdb$relation_name = "CUSTOMER";
Это выражение вернет Вам список всех индексов, принадлежащих
указанной таблице (CUSTOMER). Но в результате будут содержаться все индексы, а
не только созданные пользователем. Попробуем выделить только созданные
пользователем индексы. select RDB$INDEX_NAME
from rdb$indices
where (rdb$relation_name = "CUSTOMER")
AND NOT (RDB$INDEX_NAME STARTING WITH "RDB$");
Индексы обладают и другими свойствами, а не только именем. Попробуем узнать
некоторые из них. select RDB$INDEX_NAME, RDB$UNIQUE_FLAG, RDB$INDEX_INACTIVE, RDB$STATISTICS
from rdb$indices
where (rdb$relation_name = "CUSTOMER")
AND NOT (RDB$INDEX_NAME STARTING WITH "RDB$");
Поле RDB$UNIQUE_FLAG определяет, позволяет ли индекс двойные
значения. Если это поле имеет значение 1, то двойных значений быть не может.
RDB$INDEX_INACTIVE показывает, работает ли индекс в данный момент, т.е. активен
ли он. Когда в этом поле стоит значение 0, то индекс активен. RDB$STATISTICS -
коэффициент избирательности, используется оптимизатором для выбора стратегии
доступа при выполнении запроса.
Всем известно, что индексы строятся по одному или нескольким
полям таблицы. Приведем пример того, как можно узнать, на базе каких полей
построен индекс. Информация о полях, входящих в индекс содержится в таблице
RDB$INDEX_SEGMENTS. select RDB$FIELD_NAME, RDB$FIELD_POSITION
from rdb$index_segments where rdb$index_name = "CUSTREGION"
order by rdb$field_position;
Этот запрос вернет нам список полей, по которым построен индекс, а также
порядок полей в индексе.
В том случае, если Вы много работаете с таблицами, вносите
большое количество изменений, то может произойти разбалансировка индекса, что
приведет к увеличению времени выполнения запросов и, соответственно,
производительности в целом. Этого можно избежать, проводя перестройку индексов.
Для этого нужно, сначала деактивировав индексы, а потом активировать их. SELECT 'alter index '|| RDB$INDEX_NAME ||' INACTIVE;'
FROM RDB$INDICES
WHERE NOT (RDB$INDEX_NAME STARTING WITH "RDB$");
Этот SQL-запрос даст Вам набор строк-команд для деактивации
индексов. Поочередно выбирая получившиеся строки в программе, можно использовать
их как команды для деактивизации соответствующего индекса. Если этот запрос
выполнить в Windows ISQL, то из области результата можно будет скопировать
скрипт, выполняющий те же действия. Следующий запрос дает набор команд для
обратной процедуры. SELECT 'alter index '|| RDB$INDEX_NAME ||' ACTIVE;'
FROM RDB$INDICES
WHERE NOT (RDB$INDEX_NAME STARTING WITH "RDB$");
Деактивизация индексов полезна и тогда, когда нужно добавить большое
количество записей.
Индекс имеет такой показатель, как "полезность", который
используется InterBase-сервером для выбора оптимального плана удовлетворения
запросов. Его рекомендуется пересчитывать. Для получения скрипта, делающего это
для всех индексов, можно попробовать следующий запрос. SELECT 'SET STATISTICS INDEX '|| RDB$INDEX_NAME ||';'
FROM RDB$INDICES
WHERE NOT (RDB$INDEX_NAME STARTING WITH "RDB$");
Триггеры.
Триггер - это процедура базы данных, которая автоматически вызывается SQL
сервером при возникновении определенных событий (добавление, удаление,
обновление записей).
Попробуем узнать, какие триггеры есть в базе данных. Информация о триггерах
содержится в служебной таблице RDB$TRIGGERS. select RDB$TRIGGER_NAME from RDB$TRIGGERS
where (RDB$SYSTEM_FLAG = 0) or (RDB$SYSTEM_FLAG is NULL);
Условие этого SQL-запроса позволяет выбрать только триггеры,
созданные пользователем. Однако нужно отметить, что в результате запроса будут и
триггеры, обеспечивающие ограничения CHECK. Эти триггеры создаются не явно,
когда Вы описываете ограничение. Как же получить список триггеров, действительно
созданных пользователем. Все триггеры, обеспечивающие CHECK ограничения,
перечислены в таблице RDB$CHECK_CONSTRAINTS. Поэтому следующим запросом мы можем
их отсечь. select RDB$TRIGGER_NAME from RDB$TRIGGERS
where ((RDB$SYSTEM_FLAG = 0) or (RDB$SYSTEM_FLAG is NULL)) and
(RDB$TRIGGER_NAME not in
(select RDB$TRIGGER_NAME from RDB$CHECK_CONSTRAINTS));
Результатом будет список триггеров, созданных пользователем и выполняющих
какие-либо действия, помимо обеспечения ограничений.
В той же таблице RDB$TRIGGERS находятся и другие параметры триггера.
Попробуем извлечь их. select RDB$TRIGGER_NAME, RDB$RELATION_NAME, RDB$TRIGGER_SEQUENCE,
RDB$TRIGGER_TYPE, RDB$TRIGGER_SOURCE, RDB$TRIGGER_INACTIVE
from RDB$TRIGGERS
where ((RDB$SYSTEM_FLAG = 0) or (RDB$SYSTEM_FLAG is NULL)) and
(RDB$TRIGGER_NAME not in
(select RDB$TRIGGER_NAME from RDB$CHECK_CONSTRAINTS));
В результате мы получим не просто список триггеров, а узнаем,
какой таблице триггер принадлежит (RDB$RELATION_NAME), порядковый номер триггера
(RDB$TRIGGER_SEQUENCE), определяющий, в какой последовательности триггеры будут
выполнятся, если они одного типа и принадлежат одной таблице, тип триггера
(RDB$TRIGGER_TYPE), исходный код триггера (RDB$TRIGGER_SOURCE). Кроме того, мы
узнаем состояние триггера, активен ли он в данный момент (RDB$TRIGGER_INACTIVE).
Значение этого поля, установленное в 0, говорит о том, что триггер активен.
Скажем еще пару слов о типе триггера. Поле RDB$TRIGGER_TYPE имеет тип короткого
целого, и в нем числами зашифрован тип триггера. Посмотрим, можно ли представить
эти значения более читабельными. Различная информация о подобных зашифрованных
типах содержится в таблице RDB$TYPES. select a.RDB$TRIGGER_NAME, a.RDB$RELATION_NAME, a.RDB$TRIGGER_SEQUENCE,
b.RDB$TYPE_NAME, a.RDB$TRIGGER_SOURCE, a.RDB$TRIGGER_INACTIVE
from RDB$TRIGGERS a, RDB$TYPES b
where (a.RDB$TRIGGER_TYPE=b.RDB$TYPE) and
(b.RDB$FIELD_NAME="RDB$TRIGGER_TYPE") and
((a.RDB$SYSTEM_FLAG = 0) or (a.RDB$SYSTEM_FLAG is NULL))
and (a.RDB$TRIGGER_NAME not in (select RDB$TRIGGER_NAME
from RDB$CHECK_CONSTRAINTS));
Поле b.RDB$TYPE_NAME будет содержать расшифровку типа триггера,
хотя она и отличается от той, к которой мы привыкли. На всякий случай приведу
таблицу сооветствия значений типов, взятых из разных источников.
Код |
Значение из документации |
Значение из таблицы RDB$TYPES |
1 |
BEFORE INSERT |
PRE_STORE |
2 |
AFTER INSERT |
POST_STORE |
3 |
BEFORE UPDATE |
PRE_MODIFY |
4 |
AFTER UPDATE |
POST_MODIFY |
5 |
BEFORE DELETE |
PRE_ERASE |
6 |
AFTER DELETE |
POST_ERASE |
Триггеры - это очень хорошо. Но бывают ситуации, когда нужно
приостановить их работу. Например: нужно перенести данные из базы данных формата
dbf, где ссылки между таблицами определяются значениями в некоторых полях. Самое
простое - это перенести все значения как они есть, чтоб не нарушать ссылочную
целостность, но, если в базе данных InterBase существуют триггеры, генерирующие
уникальные значения, то возможет конфликт или нарушение ссылок. Сам попадался на
этом. По этому было бы не плохо временно остановить работу триггеров. Попробуем
получить скрипт для выполнения подобной операции. SELECT "ALTER TRIGGER " || RDB$TRIGGER_NAME || "INACTIVE;"
FROM RDB$TRIGGERS
WHERE ((RDB$SYSTEM_FLAG = 0) OR (RDB$SYSTEM_FLAG IS NULL)) AND
(RDB$TRIGGER_NAME NOT IN
(SELECT RDB$TRIGGER_NAME FROM RDB$CHECK_CONSTRAINTS));
Если выполнить этот SQL-запрос в Windows ISQL, то из области
результата можно скопировать готовый скрипт. Учтите, что в него попадут, не
только триггеры, гинерирующие уникальные значения полей, но и другие, активность
которых вполне можкт быть уместной. Поэтому рекомендую, получившийся скрипт
скорректировать.
Представления (Views)
Представления помогают нам организовать доступ к информации,
находящейся в одной или нескольких таблицах. Особенно это удобно, когда такую
информацию нужно получать часто, а условия отбора остаются неизменными. Можно ли
узнать, какие представления есть в базе данных? Они перечислены в таблице
RDB$RELATIONS вместе с таблицами. Попробуем их получить следующим SQL-запросом. select rdb$relation_name
from rdb$relations
where (rdb$system_flag = 0) and rdb$view_source is not null;
В условии отбора мы указали, что нас интересуют только объекты, созданные
пользователем (rdb$system_flag = 0), и имеют заполненное поле rdb$view_source,
что говорит о том, что мы имеем дело с представлением.
Известно, что представления строятся на базе SQL-запросов. Попробуем получить
текст этого запроса для некоторого представления. select rdb$view_source
from rdb$relations
where rdb$relation_name = "PHONE_LIST";
Поле rdb$view_source имеет тип MEMO, и в нем содержится текст SQL.
Запрос, полностью идентичный запросу для таблиц, показывает структуру
представления (возвращаемые поля, их тип и пр.). SELECT A.RDB$FIELD_NAME, A.RDB$FIELD_POSITION, A.RDB$NULL_FLAG,
A.RDB$FIELD_SOURCE, A.RDB$DEFAULT_SOURCE,
B.RDB$COMPUTED_SOURCE, B.RDB$FIELD_LENGTH,
B.RDB$FIELD_SCALE, B.RDB$FIELD_TYPE, B.RDB$FIELD_SUB_TYPE
FROM RDB$RELATION_FIELDS A, RDB$FIELDS B
WHERE A.RDB$FIELD_SOURCE = B.RDB$FIELD_NAME AND A.RDB$RELATION_NAME = "PHONE_LIST"
ORDER BY A.RDB$FIELD_POSITION ASC;
Процедуры.
Сохраненные процедуры - готовые части кода, расположенные в
базе данных и выполняющиеся на сервере. Что мы можем узнать про них из системных
таблиц базы данных. Да, практически, все! Наснем с того, что получим список
процедур. select rdb$procedure_name
from rdb$procedures
where rdb$system_flag = 0;
Все процедуры и основные их параметры содержатся в таблице rdb$procedures.
Попробуем узнать побольше о какой-либо процедуре. select RDB$PROCEDURE_INPUTS, RDB$PROCEDURE_OUTPUTS,
RDB$PROCEDURE_SOURCE, RDB$OWNER_NAME
from rdb$procedures
where rdb$procedure_name = "DEPT_BUDGET";
Показанный выше SQL-запрос вернет количество входных и выходных параметров,
исходный текст тела процедуры и имя пользователя, создавшего процедуру.
Попробуем узнать про входные и выходные параметры подробнее. select a.RDB$PARAMETER_NAME, a.RDB$PARAMETER_NUMBER,
a.RDB$PARAMETER_TYPE, b.RDB$VALIDATION_SOURCE, b.RDB$COMPUTED_SOURCE,
b.RDB$DEFAULT_SOURCE, b.RDB$FIELD_LENGTH,
b.RDB$FIELD_SCALE, b.RDB$FIELD_TYPE, b.RDB$FIELD_SUB_TYPE, b.RDB$NULL_FLAG
from RDB$PROCEDURE_PARAMETERS a, RDB$FIELDS b
where (a.RDB$FIELD_SOURCE=b.RDB$FIELD_NAME) and
(a.RDB$PROCEDURE_NAME="DEPT_BUDGET")
order by a.RDB$PARAMETER_TYPE, a.RDB$PARAMETER_NUMBER;
Этот запрос связывает две таблицы RDB$PROCEDURE_PARAMETERS и
RDB$FIELDS и возвращает имя параметра, номер параметра среди параметров одного
типа, тип параметра (0-входной, 1-выходной), а далее уже знакомые поля из
таблицы RDB$FIELDS.
Функции.
Функции позволяют наращивать возможности InterBase-сервера за
счет подключения к базе данных модулей из dll, которые могут быть реализованы на
любом языке программирования. Прежде чем пользоваться функциями, давайте сначала
узнаем, а какие функции декларированы в базе данных. Основная информация о
функциях находится в таблицах RDB$FUNCTIONS и RDB$FUNCTION_ARGUMENTS. select rdb$function_name
from rdb$functions
where ((rdb$system_flag = 0) or (rdb$system_flag is null));
Этот запрос вернет Вам список всех декларированных функций. Но это только
список. Давайте посмотрим, где находятся эти функции и под каким именем их
вызывать из библиотек. select RDB$FUNCTION_NAME, RDB$MODULE_NAME,
RDB$ENTRYPOINT, RDB$RETURN_ARGUMENT
from rdb$functions
where ((rdb$system_flag = 0) or (rdb$system_flag is null));
Приведенный выше запрос возвращает, кроме наименования функции,
под которым она известна в базе данных, наименование модуля, точку входа
(наименование в модуле), позицию аргумента, возвращаемого программе вызова. Сами
аргументы функции содержаться в таблице RDB$FUNCTION_ARGUMENTS. Покажем, как
можно узнать, какие аргументы имеет некоторая функция. SELECT a.RDB$FUNCTION_NAME, b.RDB$ARGUMENT_POSITION,
b.RDB$MECHANISM, b.RDB$FIELD_TYPE,
b.RDB$FIELD_SCALE, b.RDB$FIELD_LENGTH, b.RDB$FIELD_SUB_TYPE
FROM RDB$FUNCTIONS a, RDB$FUNCTION_ARGUMENTS b
WHERE (a.RDB$FUNCTION_NAME = b.RDB$FUNCTION_NAME) and
((a.RDB$SYSTEM_FLAG = 0) OR (a.RDB$SYSTEM_FLAG IS NULL))
and (b.RDB$ARGUMENT_POSITION<>a.RDB$RETURN_ARGUMENT);
Этот запрос возвратит для кажной функции информацию о входных
аргументах (их порядок, механизм передачи, о котором можно почитать в
документации, а далее уже известные вещи: тип, длина и т.д.). Условие
(b.RDB$ARGUMENT_POSITION <> a.RDB$RETURN_ARGUMENT) отбирает только входные
аргументы. Если нужно посмотреть выходные аргументы, то можно воспользоваться
следующим запросом. SELECT a.RDB$FUNCTION_NAME, b.RDB$ARGUMENT_POSITION,
b.RDB$MECHANISM, b.RDB$FIELD_TYPE,
b.RDB$FIELD_SCALE , b.RDB$FIELD_LENGTH, b.RDB$FIELD_SUB_TYPE
FROM RDB$FUNCTIONS a, RDB$FUNCTION_ARGUMENTS b
WHERE (a.RDB$FUNCTION_NAME = b.RDB$FUNCTION_NAME) and
((a.RDB$SYSTEM_FLAG = 0) OR (a.RDB$SYSTEM_FLAG IS NULL))
and (b.RDB$ARGUMENT_POSITION = a.RDB$RETURN_ARGUMENT);
Генераторы.
Генераторы позволяют создавать уникальные идентификаторы,
значениями которых удобно заполнять ключевые поля таблиц. Использую служебные
таблицы базы данных, можно достаточно легко определить, какие генераторы есть и
в какие значения они установлены. Вся информация о генераторах сосредоточена в
таблице RDB$GENERATORS. Посмотрим, как можно получить список генераторов,
созданных пользователем. select rdb$generator_name
from rdb$generators
where ((rdb$system_flag = 0) or (rdb$system_flag is null));
Следующий SQL-запрос позволит посмотреть текущие значения генераторов. select distinct gen_id(CUST_NO_GEN, 0) from RDB$GENERATORS;
Этот запрос возвращает значение генератора CUST_NO_GEN.
Исключения.
Исключения - это созданные пользователем ошибки с
ассоциированными сообщениями, которые могут быть использованы в сохраненных
процедурах и триггерах. Основываясь на служебной таблице RDB$EXCEPTIONS, можно
узнать какие исключения и с какими сообщениями присутствуют в базе данных. select rdb$exception_name, RDB$MESSAGE
from rdb$exceptions
where ((rdb$system_flag = 0) or (rdb$system_flag is null));
Зависимости.
Представьте себе такую картину: Вы создали таблицу, у нее есть
какие-то поля. Потом Вы создали представление, которое выбирает из этой таблицы
некоторые поля. И вот у Вас возникла необходимость удалить таблицу или некоторые
ее поля. Что будет с представлением. Скорее оно работать не будет. Чтобы
подобных ситуаций не происходило, InterBase-сервер отслеживает зависимости между
объектами в базе данных и хранит их в служебной таблице RDB$DEPENDENCIES.
Описание полей этой таблицы можно найти в документации, а тут я попробую
привести примеры запросов, которые позволят посмотреть, какой объект от какого
зависит. select distinct a.RDB$DEPENDENT_NAME, a.RDB$DEPENDENT_TYPE, b.RDB$TYPE_NAME
from RDB$DEPENDENCIES a, RDB$TYPES b
where (a.RDB$DEPENDENT_TYPE=b.RDB$TYPE) and
(b.RDB$FIELD_NAME="RDB$OBJECT_TYPE")
and (a.RDB$DEPENDED_ON_NAME = "JOB");
Приведенный выше запрос показывает, какие объекты зависят от
объекта JOB. a.RDB$DEPENDENT_NAME - наименование объекта, который зависит от
JOB, a.RDB$DEPENDENT_TYPE - тип этого объекта (код), b.RDB$TYPE_NAME -
расшифровка типа объекта (представление, процедура и пр.).
А приведенный ниже запрос показывает, от каких объектов зависит объект
"PHONE_LIST". select a.RDB$DEPENDED_ON_NAME, a.RDB$FIELD_NAME, a.RDB$DEPENDED_ON_TYPE,
b.RDB$TYPE_NAME
from RDB$DEPENDENCIES a, RDB$TYPES b
where (a.RDB$DEPENDED_ON_TYPE=b.RDB$TYPE) and
(b.RDB$FIELD_NAME="RDB$OBJECT_TYPE") and
a.RDB$DEPENDENT_NAME="PHONE_LIST";
a.RDB$DEPENDED_ON_NAME - наименование объекта, который
используется при работе PHONE_LIST. a.RDB$FIELD_NAME - имена полей
вышеупомянутых объектов, которые используются объектом PHONE_LIST. Далее, как и
в предыдущем запросе, возвращается тип объекта, содержащегося в
a.RDB$DEPENDED_ON_NAME.
Пользователи, права.
Для того, что бы получить доступ к базе данных, нужно быть
пользователем, прописанным на InterBase-сервере, и иметь пароль. Но этого не
достаточно, чтобы оперировать с объектами базы данных. Пользователь должен иметь
права на выполнение той или иной операции.
Посмотреть, какие пользователи известны серверу можно, используя базу данных
Isc4.gdb. select USER_NAME, FIRST_NAME, MIDDLE_NAME, LAST_NAME
from USERS
order by USER_NAME;
Этот запрос даст список имен пользователей, а также их имена и фамилии.
Помимо пользователей обычных можно определять роли, давать им права, а потом
пользователям назначать роли.
Посмотрим, какие роли есть в базе данных. select * from RDB$ROLES;
Поле RDB$ROLE_NAME - содержит имя роли, а поле RDB$OWNER_NAME - содержит имя
пользователя, создавшего роль.
Посмотрим теперь, что можно узнать про права того или иного пользователя, по
отношению к объектам базы данных. Информацию об этом можно найти в таблице
RDB$USER_PRIVILEGES. select RDB$GRANTOR, RDB$PRIVILEGE, RDB$GRANT_OPTION, RDB$RELATION_NAME
from RDB$USER_PRIVILEGES
where RDB$USER="SVETA";
Приведенный выше SQL-запрос показывает все права пользователя
SVETA. Поле RDB$GRANTOR - содержит имя пользователя, предоставившего это право.
RDB$PRIVILEGE - описывает привилегию (расшифровка значений приведена в
документации). RDB$GRANT_OPTION определяет, может ли пользователь, получивший
эту привилегию, передать ее другому пользователю. Если значение равно единице,
то такая возможность есть. RDB$RELATION_NAME - наименование объекта базы данных,
для которого привилегия допустима. А как узнать привилегии, назначенные ролям? select a.RDB$USER, a.RDB$GRANTOR, a.RDB$PRIVILEGE,
a.RDB$GRANT_OPTION, a.RDB$RELATION_NAME
from RDB$USER_PRIVILEGES a, RDB$ROLES b
where a.RDB$USER = b.RDB$ROLE_NAME;
Этот запрос почти идентичен предыдущему по выдаваемым результатам, кроме поля
a.RDB$USER. Оно содержит, в данном случае, наименование роли.
Изменив немного предыдущий запрос, можно узнать, права каких ролей кому
предоставлены. select a.RDB$USER, a.RDB$GRANTOR, a.RDB$PRIVILEGE,
a.RDB$GRANT_OPTION, a.RDB$RELATION_NAME
from RDB$USER_PRIVILEGES a, RDB$ROLES b
where a.RDB$RELATION_NAME = b.RDB$ROLE_NAME;
В дополнение.
В дополнение ко всему выше сказанному вот дописываю.
На днях один знакомый по Internet спросил, как можно изменить
параметры поля, не теряя данных (конкретно: поле было NOT NULL, нужно это
убрать). Я попробовал для этого следующее SQL-выражение: UPDATE RDB$RELATION_FIELDS
SET RDB$NULL_FLAG = NULL
WHERE RDB$RELATION_NAME = "CUSTOMER" AND (RDB$FIELD_NAME = "CUSTOMER");
|