Вашему вниманию предлагается пример организации данных типа Registry в БД. В таблице хранятся разнородные данные, процедуры обеспечивают выбору всей иерархии в нужном порядке и поиск по ключу. Хотя это и не самый быстрый способ (безусловно, обращение к базе данных медленнее, чем к Registry Windows 95 или Windows NT), зато есть возможность настойки системы.
Такую структуру можно использовать для хранения настроек пользователя независимо от клиентского компьютера, с которого пользователь работает с базой данных (естественно на каждого – свои настройки) и т. п.
Примечание. При вставке строк в качестве имени ключа (key_name) не допускаются символы '\'. Для процедуры Find_Regitry_Entry строку FULLKEY нужно задавать как 'rootkey1\secondkey\'.
Если вы поместите этот текст в скрипт, то не забудьте добавить в конец файла пару пустых переводов строки.
CONNECT "C:\MYDATABASE.GDB" USER "SYSDBA" PASSWORD "masterkey";
/* Таблица для хранения данных "Regitry" */
CREATE TABLE REGISTRY (
Key_code integer not null,
Key_parent integer ,
Key_name char(64) not null,
Key_type smallint not null,
Key_string char(255) ,
Key_integer integer,
Key_date date ,
Key_float double precision,
Key_blob blob,
constraint pk_registry primary key(Key_code));
ALTER TABLE REGISTRY ADD CONSTRAINT FK_REGISTRY
FOREIGN KEY (key_parent) references REGISTRY;
CREATE EXCEPTION NOT_UNIQUE_NAME 'Not unique name in group';
CREATE EXCEPTION INTEGRITY_ERROR 'Error in hierarchy';
SET TERM !! ;
CREATE PROCEDURE GET_REGISTRY_SUBKEYS(parent_code integer, lev smallint)
RETURNS( Key_code integer,
Key_name varchar(64),
Key_type smallint,
level_num smallint)
AS
BEGIN
FOR SELECT Key_code, Key_name, Key_type
FROM REGISTRY
WHERE Key_parent = :parent_code
INTO :Key_code, :Key_name, :Key_type
DO
BEGIN
level_num = lev;
SUSPEND;
FOR SELECT Key_code, Key_name, level_num, Key_type
FROM GET_REGISTRY_SUBKEYS(:Key_code, :lev+1)
INTO :Key_code, :Key_name, :level_num, :Key_type
DO SUSPEND;
END
EXIT;
END!!
CREATE PROCEDURE GET_REGISTRY
RETURNS( Key_code integer,
Key_name varchar(64),
Key_type smallint,
level_num smallint)
AS
BEGIN
FOR SELECT Key_code, Key_name, Key_type
FROM REGISTRY
WHERE Key_parent is null
INTO :Key_code, :Key_name, :Key_type
DO
BEGIN
level_num = 0;
SUSPEND;
FOR SELECT Key_code, Key_name, level_num, key_type
FROM GET_REGISTRY_SUBKEYS(:Key_code, 1)
INTO :Key_code, :Key_name, :level_num, :key_type
DO SUSPEND;
END
EXIT;
END!!
CREATE PROCEDURE FIND_REGISTRY_SUBKEY( FullKey VarChar(1000),
PartialKey VarChar(1000),
Parent Integer)
RETURNS( Key_code integer,
Key_name varchar(64),
Key_type smallint )
AS
BEGIN
SELECT Key_code, Key_name, key_type
FROM REGISTRY
WHERE Key_parent = :parent AND
:FullKey LIKE :PartialKey||key_name||'\%'
INTO :Key_code, :Key_name, :key_type;
IF (Key_code is null) THEN EXIT;
IF (PartialKey||Key_name||'\' <> FullKey) THEN
BEGIN
key_type = NULL;
SELECT Key_code, Key_name, key_type
FROM FIND_REGISTRY_SUBKEY( :FullKey, :PartialKey||:key_name||'\', :Key_code)
INTO :Key_code, :Key_name, :key_type;
END
IF (Key_type is not null) THEN SUSPEND;
END!!
CREATE PROCEDURE FIND_REGISTRY_ENTRY( FullKey VarChar(1000))
RETURNS( Key_code integer,
Key_name varchar(64),
Key_type smallint)
AS
BEGIN
SELECT Key_code, Key_name, key_type
FROM REGISTRY
WHERE Key_parent is null AND
:FullKey LIKE key_name||'\%'
INTO :Key_code, :Key_name, :key_type;
IF (Key_code is null) THEN EXIT;
IF (Key_name||'\' <> FullKey) THEN
BEGIN
key_type = NULL;
SELECT Key_code, Key_name, key_type
FROM FIND_REGISTRY_SUBKEY( :FullKey, :key_name||'\', :Key_code)
INTO :Key_code, :Key_name, :key_type;
END
IF (Key_type is not null) THEN SUSPEND;
END!!
CREATE TRIGGER REGISTRY_INSERT FOR REGISTRY
BEFORE INSERT AS
BEGIN
IF (new.key_parent is null) THEN
IF (EXISTS(SELECT key_name FROM REGISTRY
WHERE key_parent is null AND
key_name = new.key_name)) THEN
EXCEPTION NOT_UNIQUE_NAME;
IF (new.key_parent is not null) THEN
IF (EXISTS(SELECT key_name FROM REGISTRY
WHERE key_parent=new.key_parent AND key_name = new.key_name)) THEN
EXCEPTION NOT_UNIQUE_NAME;
SELECT MAX(key_code) FROM REGISTRY
INTO new.key_code;
IF (new.key_code is null) then new.key_code = 1;
ELSE new.key_code = new.key_code + 1;
END!!
CREATE TRIGGER REGISTRY_UPDATE FOR REGISTRY
BEFORE UPDATE
AS
BEGIN
IF (new.key_name <> old.key_name) THEN
BEGIN
IF (new.key_parent is null) THEN
IF (EXISTS(SELECT key_name FROM REGISTRY
WHERE key_parent is null AND key_name = new.key_name)) THEN
EXCEPTION NOT_UNIQUE_NAME;
IF (new.key_parent is not null) THEN
IF (EXISTS(SELECT key_name FROM REGISTRY
WHERE key_parent=new.key_parent AND key_name = new.key_name)) THEN
EXCEPTION NOT_UNIQUE_NAME;
END
IF ((EXISTS(SELECT key_code
FROM GET_REGISTRY_SUBKEYS(new.key_code,0)
WHERE key_code = new.key_parent)) OR
(new.key_parent = new.key_code)) THEN
EXCEPTION INTEGRITY_ERROR;
END!!
SET TERM ; !!
COMMIT;