Criando variáveis ? Utilize o Associative Array
Sergio,
estou dando manutenção em um sistema que tem dezenas de variáveis v_ criadas para cálculo e acho que não é uma boa prática. Como poderia mudar isso ?
V.
Então, eu também não sou muito fã de sair criando dezenas de variáveis, pois isso envolve tipificar cada uma, atribuir e tudo o mais que envolve uma operação básica que as utiliza. Quando os campos são utilizados para inserção e são compatíveis com um ROWTYPE, fica muito mais fácil utilizar uma variável desse tipo, inclusive, escrevi sobre isso no artigo abaixo:
Infelizmente essa abordagem não atende a todas as necessidades, mas sempre podemos contar com o Associative Array.
Primeiramente, vamos montar um exemplo onde precisamos separar valores por tipo de pagamento. Vamos criar uma tabela chamada PAGAMENTOS. Será uma tabela desnormalizada e simples só para exemplificarmos.
CREATE TABLE pagamentos
(
tipo_pagamento VARCHAR2(150)
,valor NUMBER
)
/
Table PAGAMENTOS created.
Agora vamos inserir alguns dados:
INSERT INTO pagamentos VALUES ('CARTÃO DE CRÉDITO',150)
/
INSERT INTO pagamentos VALUES ('CARTÃO DE CRÉDITO',100)
/
INSERT INTO pagamentos VALUES ('CARTÃO DE CRÉDITO',50)
/
INSERT INTO pagamentos VALUES ('DINHEIRO',70)
/
INSERT INTO pagamentos VALUES ('DINHEIRO',170)
/
INSERT INTO pagamentos VALUES ('DINHEIRO',10)
/
INSERT INTO pagamentos VALUES ('CARTÃO DE DÉBITO',80)
/
INSERT INTO pagamentos VALUES ('CARTÃO DE DÉBITO',90)
/
INSERT INTO pagamentos VALUES ('CARTÃO DE DÉBITO',200)
/
INSERT INTO pagamentos VALUES ('CARTÃO DE DÉBITO',100)
/
INSERT INTO pagamentos VALUES ('CARTÃO DE DÉBITO',105)
/
Vamos criar um bloco anônimo que irá somar os valores de acordo com o tipo de pagamento.
DECLARE
-- Type based variable and index
TYPE value_table IS TABLE OF NUMBER INDEX BY VARCHAR2(50);
v_value_table value_table;
v_key VARCHAR2(50);
-- Cursor
CURSOR c_pagamentos
IS
SELECT x.tipo_pagamento
,x.valor
FROM pagamentos x;
r_pagamentos c_pagamentos%ROWTYPE;
--
-- Increment values
--
PROCEDURE save_values
(
p_value_type IN VARCHAR2
,p_value IN NUMBER
)
AS
BEGIN
v_value_table(p_value_type) := v_value_table(p_value_type) + NVL(p_value,0);
EXCEPTION
WHEN no_data_found THEN
-- Se não existir o índice atual, atribui o valor
v_value_table(p_value_type) := NVL(p_value,0);
END save_values;
BEGIN
-- Limpa a tabela
v_value_table.DELETE;
-- Soma os valores de acordo com o tipo de pagamento
FOR r_pagamentos IN c_pagamentos
LOOP
save_values(R_PAGAMENTOS.tipo_pagamento, R_PAGAMENTOS.valor);
END LOOP;
-- Lê os resultados
v_key := v_value_table.FIRST;
WHILE v_Key IS NOT NULL
LOOP
DBMS_OUTPUT.put_line('[ CHAVE ] ' || RPAD(v_key,20) ||' [ VALOR ] ' || v_value_table(v_key));
v_key := v_value_table.NEXT(v_Key);
END LOOP;
-- Buscando os valores pelo índice
DBMS_OUTPUT.put_line('[ VALOR ] ' || v_value_table('DINHEIRO'));
DBMS_OUTPUT.put_line('[ VALOR ] ' || v_value_table('CARTÃO DE DÉBITO'));
DBMS_OUTPUT.put_line('[ VALOR ] ' || v_value_table('CARTÃO DE CRÉDITO'));
-- Somando os cartões
save_values('CARTÃO',v_value_table('CARTÃO DE CRÉDITO') + v_value_table('CARTÃO DE DÉBITO'));
DBMS_OUTPUT.put_line('[ VALOR CARTÃO ] ' || v_value_table('CARTÃO'));
END;
Executando…
PL/SQL procedure successfully completed.
[ CHAVE ] CARTÃO DE CRÉDITO [ VALOR ] 300
[ CHAVE ] CARTÃO DE DÉBITO [ VALOR ] 575
[ CHAVE ] DINHEIRO [ VALOR ] 250
[ VALOR ] 250
[ VALOR ] 575
[ VALOR ] 300
[ VALOR CARTÃO ] 875
Veja que apesar de eu ter incluído índices de acordo com a leitura da tabela, eu também criei manualmente a entrada CARTÃO para salvar os valores somados de DÉBITO e CRÉDITO.
Com apenas quatros valores a serem guardados e computados, pode não parecer valer a pena utilizar um Associative Array, mas imagine quando falamos de 10 ou 20 deles.
Espero ter ajudado !
boa explicaçao