[firebase-br] Trabalhando com Hierarquia no Firebird
Ivan Guimarães Meirelles
igmeirelles em gmail.com
Seg Ago 27 07:21:37 -03 2007
Como havia prometido, segue ai um passo-a-passo para quem quiser trabalhar
com hierarquia no Firebird.
O exemplo que vou montar aqui será baseado em um cadastro de funcionários e
seus supervisores, que também são funcionários:
1 - Crie a seguinte tabela:
CREATE TABLE FUNCIONARIOS
(
IDFUNCIONARIO INTEGER NOT NULL,
NOME VARCHAR(30),
IDSUPERVISOR INTEGER
);
2 - Defina o campo IDFUNCIONARIO como chave primária:
alter table FUNCIONARIOS
add constraint PK_FUNCIONARIOS primary key (IDFUNCIONARIO);
3 - Crie um auto-relacionamento nessa tabela, ligando IDSUPERVISOR a
IDFUNCIONARIO, criando uma chave estrangeira:
alter table FUNCIONARIOS
add constraint FK_FUNC_SUPE foreign key (IDSUPERVISOR)
references FUNCIONARIOS(IDFUNCIONARIO) on update CASCADE;
4 - Vamos alimentar essa tabela. Obs.: O funcionário que não tiver
supervisor, terá o campo IDSUPERVISOR como NULL:
insert into funcionarios(idfuncionario, nome, idsupervisor) values(1, 'MARIA
APARECIDA', null);
insert into funcionarios(idfuncionario, nome, idsupervisor) values(2, 'JOAO
DA SILVA', 1);
insert into funcionarios(idfuncionario, nome, idsupervisor) values(3,
'AGUINALDO OLIVEIRA', 1);
insert into funcionarios(idfuncionario, nome, idsupervisor) values(4,
'RENATA FRANCA', 3);
insert into funcionarios(idfuncionario, nome, idsupervisor) values(5,
'GISELE SOUZA', 3);
insert into funcionarios(idfuncionario, nome, idsupervisor) values(6, 'LAURA
BONIELI', 3);
insert into funcionarios(idfuncionario, nome, idsupervisor) values(7, 'HILDA
CONCEICAO', 6);
insert into funcionarios(idfuncionario, nome, idsupervisor) values(8,
'RICARDO SOUZA', 6);
insert into funcionarios(idfuncionario, nome, idsupervisor) values(9,
'MARCOS DUILIO', 8);
5 - Precisaremos aqui, declarar duas UDF's: STRLEN e LPAD, essas UDF's fazem
parte da instalação do Firebird:
DECLARE EXTERNAL FUNCTION STRLEN
CSTRING(32767)
RETURNS INTEGER BY VALUE
ENTRY_POINT 'IB_UDF_strlen' MODULE_NAME 'ib_udf';
DECLARE EXTERNAL FUNCTION LPAD
CSTRING(255),
INTEGER,
CSTRING(1)
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_lpad' MODULE_NAME 'ib_udf';
6 - Criaremos agora uma Stored Procedure Recursiva para similar uma
funcionalidade do Oracle, quando se trata de hierarquia:
CREATE PROCEDURE FUNC_HIERARQ (
id integer,
idinicial varchar(30))
returns (
codigo varchar(30),
nome varchar(30),
idfuncionario integer,
idsupervisor integer,
nivel integer)
as
declare variable aux integer;
begin
if (id is null) then
begin
for
select lpad(FC.idfuncionario, 2, '0'), FC.nome,
FC.idfuncionario, FC.idsupervisor
from FUNCIONARIOS FC where FC.idsupervisor is null
into
:codigo, :nome, :idfuncionario, :idsupervisor
do
begin
nivel = (strlen(:codigo) + 1) / 3;
suspend;
for select FH.codigo, FH.nome, FH.idfuncionario,
FH.idsupervisor
from FUNC_HIERARQ(:codigo, :codigo) FH
into :codigo, :nome, :idfuncionario, :idsupervisor
do
begin
nivel = (strlen(:codigo) + 1) / 3;
suspend;
end
end
end
if (not id is null) then
begin
for
select coalesce(:idinicial,'') || '.' ||
lpad(FC.idfuncionario, 2, '0'), FC.nome, FC.idfuncionario, FC.idsupervisor
from FUNCIONARIOS FC where FC.idsupervisor = :id
into
:codigo, :nome, :aux, :idsupervisor
do
begin
idfuncionario = :aux;
nivel = (strlen(:codigo) + 1) / 3;
suspend;
for select FH.codigo, FH.nome, FH.idfuncionario,
FH.idsupervisor from FUNC_HIERARQ(:aux, :codigo) FH
into :codigo, :nome, :idfuncionario, :idsupervisor
do
begin
nivel = (strlen(:codigo) + 1) / 3;
suspend;
end
end
end
end;
7 - A Stored Procedure abaixo mostra um exemplo de utilização da procedure
FUNC_HIERARQ:
CREATE PROCEDURE LISTA_FUNCIONARIOS returns ( relacao varchar(100) )
as
begin
for SELECT LPAD(nome, STRLEN(nome) + (nivel * 10) - 10, ' ') FROM
func_hierarq(null, null)
into :relacao do suspend;
end;
Depois de ter criado as procedures, para usá-las basta fazer assim:
select * from func_hierarq(null, null) --<-- e vc terá o seguinte retorno:
CODIGO | NOME | IDFUNCIONARIO | IDSUPERVISOR | NIVEL
---------------+--------------------+---------------+--------------+-------
01 | MARIA APARECIDA | 1 | <NULL> | 1
01.02 | JOAO DA SILVA | 2 | 1 | 2
01.03 | AGUINALDO OLIVEIRA | 3 | 1 | 2
01.03.04 | RENATA FRANCA | 4 | 3 | 3
01.03.05 | GISELE SOUZA | 5 | 3 | 3
01.03.06 | LAURA BONIELI | 6 | 3 | 3
01.03.06.07 | HILDA CONCEICAO | 7 | 6 | 4
01.03.06.08 | RICARDO SOUZA | 8 | 6 | 4
01.03.06.08.09 | MARCOS DUILIO | 9 | 8 | 5
ou então:
select * from lista_funcionarios --<-- e vc terá o seguinte retorno:
RELACAO
----------------------------------
MARIA APARECIDA
JOAO DA SILVA
AGUINALDO OLIVEIRA
RENATA FRANCA
GISELE SOUZA
LAURA BONIELI
HILDA CONCEICAO
RICARDO SOUZA
MARCOS DUILIO
Agora é com vocês... isso foi apenas uma idéia do que é possível se fazer
com o FireBird... basta ter um pouco de criatividade.
Por exemplo: Grupos e subgrupos de mercadorias com hierarquia, Centros de
Custo, Planos de Contas, Balancetes e muito mais...
Pedras, Xingamentos, Elogios, Dúvidas e/ou Sugestões... podem me contatar
por e-mail.
Um abraço a todos...
Ivan Guimarães Meirelles
Três Lagoas/MS - igmeirelles em gmail.com
Mais detalhes sobre a lista de discussão lista