Edgard Leal

My personal blog hosted on Github using Jekyll

Home View on GitHub
18 December 2012
Logo do firebird sistema de gerenciamento de banco de dados

Uma das reclamações das pessoas que começam a utilizar o FireBird é a falta do auto-incremento como é contrados em sistemas como SQL Server e MySQL. Ainda não vamos discutir os prós e contras de se utilizar generators(Sequences), mas criei um código para me auxiliar na tarefa de preparar o banco de dados para rotinas de replicação e que serve para solucionar este problema.

A rotina abaixo busca por tabelas no banco de dados que contenha chaves primárias de apenas um campo, caso encontre, cria o GENERATOR (SEQUENCE), e a TRIGGER correspondente para gerar o auto-incremento destas tabelas.

create or alter procedure prc_list_unique_fields_of_table(tablename varchar(32))
returns(fieldname varchar(32))
as
begin
for Select distinct s.rdb$field_name from rdb$indices i inner join
rdb$index_segments s on s.rdb$index_name = i.rdb$index_name
where upper(i.rdb$relation_name) = upper(:tablename) and rdb$unique_flag = 1
into :fieldname do
begin

suspend;
end
end

create or alter procedure prc_generate_auto_inc
as
declare variable sql varchar(8000);
declare variable table_name varchar(32);
declare variable key_count integer;
declare variable key_name varchar(32);
declare variable GENERATOR_OR_TRIGGER_EXISTS INTEGER;
declare variable i integer;
declare variable SERVER_COUNT INTEGER; --INDICA A QUANTIDADE DE SERVIDORES
--PARA O CADO DE REPLICAÇÃO DO BANCO
declare variable GENERATOR_NAME VARCHAR(32);
begin

i = 0;
SERVER_COUNT = 1;
for Select TRIM(r.rdb$relation_name) from rdb$relations r
where r.rdb$relation_type = 0 and r.rdb$flags = 1 into :table_name do
begin
sql = '';
i = 0;
for Select * from prc_list_unique_fields_of_table(:table_name) into :key_NAME do
begin
-- Utiliza a procedure criada anteriormente
-- foi utilizado o loop, porque se existir apenas uma chave, o valor ja estara
-- atribuido
i = i + 1;
end --for
GENERATOR_NAME = 'GEN_' || :TABLE_NAME || '_ID';
GENERATOR_OR_TRIGGER_EXISTS = NULL;
EXECUTE statement 'SELECT 1 FROM RDB$GENERATORS ' ||
' WHERE RDB$GENERATOR_NAME = ''GEN_' || :TABLE_NAME ||
'_ID'' ' INTO :generator_or_trigger_exists;

if (GENERATOR_OR_TRIGGER_EXISTS IS NULL ) then
if (i = 1) then
begin
execute statement 'create generator GEN_' || :TABLE_NAME || '_ID';
EXECUTE STATEMENT 'CREATE TRIGGER ' || :TABLE_NAME || '_BI FOR ' ||
:TABLE_NAME || ' ACTIVE BEFORE INSERT POSITION 0 AS begin ' ||
' IF(NEW.' || :KEY_NAME || ' IS NULL) THEN new.' || :KEY_NAME ||
' = GEN_ID(GEN_' || :TABLE_NAME || '_ID,' ||
CAST(:SERVER_COUNT AS VARCHAR(5)) || '); END';
end--if
end--FOR
end

Recursos utilizados nestes scripts:
TRIM: retorna o texto informado no parâmetro sem os espaços a esquerda e direita.
EXECUTE STATEMENT: Execute um comando contido na string, muito útil para criação de consultas  
            dinamicamente.
RDB$RELATIONS: Tabela do sistema que contem todas as tabelas e views do banco de dados.
UPPER: Retorna o parâmetro informado em caixa alta (todas as letras maiúsculas )
CAST: Converte um valor para um determinado tipo de dados. No nosso exemplo foi convertido um valor inteiro para texto ( varchar(5) ).



blog comments powered by Disqus