Escolar Documentos
Profissional Documentos
Cultura Documentos
[Nota] O código abaixo foi enviado por Luciano C. dos Santos, e fornece uma alternativa para
aqueles que não querem ou não gostam de usar UDFs em seus bancos de dados. A função de cada
procedure está descrita como comentário, no código da mesma.
Estas são as SPs que utilizo como auxiliares no desenvolvimento dos meus sistemas (no lugar de
UDFs). Vale observar que as escrevi bem no início do meu trabalho com FB, portanto as técnicas
de programação ainda podem ser um tanto rudimentares, mas funcionam. Quero alertar que
antes que as utilizem, façam testes, pois embora para mim estejam corretas, podem não ter o
comportamento esperado por outras pessoas.
Caso você encontre falhas ou melhore as funções, envie uma cópia para o meu email (abaixo).
Em tempo, as funções estão em ordem alfabética e como pode haver dependências entre elas,
atente para a ordem de criação das mesmas no banco de dados.
*********************************************************
CREATE PROCEDURE FU_ABS(
WVAR DOUBLE PRECISION)
RETURNS (
R_ABS DOUBLE PRECISION)
AS
begin
/*
devolve o valor Absoluto de um número.
-123,47 ou 123,47 devolve sempre 123,47
*/
if (:wvar is not null) then begin
if (:wvar < 0.0000) then
r_abs = :wvar * -1;
else
r_abs = :wvar;
end
suspend;
end
===================================
CREATE PROCEDURE FU_ALLTRIM(
WVAR VARCHAR(8192))
RETURNS (
R_ALLTRIM VARCHAR(8192))
AS
DECLARE VARIABLE T SMALLINT;
begin
/*
Devolve um string sem espaços
*/
select r_Len from Fu_Len(:wvar) into :t;
r_alltrim = '';
while ((:wvar is not null) and (:t > 0)) do begin
if (substring(:wvar from 1 for 1) <> ' ') then
r_alltrim = :r_alltrim || substring(:wvar from 1 for 1);
wvar = substring(:wvar from 2 for 8191);
t = :t - 1;
end
suspend;
end
====================================
CREATE PROCEDURE FU_BEFORE_AFTER(
WPES VARCHAR(8192),
WVAR VARCHAR(8192),
WTIP CHAR(1))
RETURNS (
WRET VARCHAR(8192))
AS
declare variable wint smallint;
declare variable wlen smallint;
begin
/*
Devolve os caracteres "Anteriores" ou "Posteriores" de
um string tomando como base "WPES"
*/
wtip = upper(:wtip);
select result from Fu_Pos(:wpes, :wvar) into :wint;
if (:wtip = 'B') then -- Before
begin
if (:wint = 0) then
wret = wpes;
else
select r_Copy from Fu_Copy(:wvar, 1, (:wint - 1)) into :wret;
end
else begin -- After
if (:wint = 0) then
wret = '';
else begin
select r_Len from Fu_Len(:wpes) into :wlen;
select r_Copy from Fu_Copy(:wvar, (:wint + :wlen), 8191) into
:wret;
end
end
suspend;
end
================================================
CREATE PROCEDURE FU_CENTRO(
WSTR VARCHAR(8192),
WTAM SMALLINT)
RETURNS (
R_CENTRO VARCHAR(8192))
AS
DECLARE VARIABLE I SMALLINT;
DECLARE VARIABLE T SMALLINT;
DECLARE VARIABLE S VARCHAR(8192);
begin
/*
Devolve um string Centralizado Com o tamanho "WRAM"
*/
select r_Len from Fu_Len(:wstr) into :t;
if (:t > :wtam) then
select r_Copy from Fu_Copy(:wstr, 1, :wtam) into :r_centro;
else if (:t = :wtam) then
r_centro = :wstr;
else begin
select r_div from Fu_div((:wtam - :t), 2) into :i;
select r_replicate from Fu_replicate(:i, ' ') into :s;
wstr = :s || :wstr;
select r_replicate from Fu_replicate(((:wtam - :t) - :i), ' ') into
:s;
r_centro = :wstr || :s;
end
suspend;
end
==============================================
CREATE PROCEDURE FU_CLASS(
WSTR VARCHAR(8192),
WSUB VARCHAR(8192),
WDEL CHAR(1),
WORD CHAR(1))
RETURNS (
R_RET VARCHAR(8192))
AS
declare variable wpos smallint;
declare variable tra1 varchar(8192);
declare variable wfez smallint = 1;
begin
/*
Insere "WSUB" em "WSTR" na ordem ascending ou
descending (conforme "WORD"). "WSTR" deve estar delimitada por
"WDEL"
*/
select result from Fu_pos(:wdel, :wstr) into :wpos;
select r_copy from Fu_Copy(:wstr, 1, (:wpos - 1)) into :tra1;
if (:word = 'A') then --
Ordem Ascending...
begin
if (:wsub < :tra1) then -
- Se já for a primeira
r_ret = :wsub || :wdel || :wstr; --
Concatenar
else begin -
- Senão...
select r_last_pos from Fu_last_pos(:wdel, :wstr) into :wpos;
-- Última Posição do delimitador
select r_copy from Fu_Copy(:wstr, (:wpos + 1), 8191) into :tra1;
-- Última String
if (:wsub >= :tra1) then --
Se for a última
r_ret = :wstr || :wdel || :wsub; --
Concatenar
else begin --
Senão
select result from Fu_pos(:wdel, :wstr) into :wpos;
-- Posição do delimitador
select r_copy from Fu_Copy(:wstr, 1, (:wpos - 1)) into :tra1;
-- Primeira String
r_ret = :tra1 || :wdel; --
... e concatenar
select r_copy from Fu_Copy(:wstr, (:wpos + 1), 8191) into :wstr;
-- STR resultante
while (:wfez = 1) do begin --
Enquanto não achar o lugar
select result from Fu_pos(:wdel, :wstr) into :wpos; -
- Posição do delimitador ns STR resultante
if (:wpos = 0) then -- Se
não tem mais...
tra1 = :wstr; --
Inicializo :TRA1
else --
Senão...
select r_copy from Fu_Copy(:wstr, 1, (:wpos - 1)) into :tra1; --
Defino
if (:wsub <= :tra1) then --
Comparo
begin
r_ret = :r_ret || :wsub || :wdel; --
Concateno se é o lugar
select r_copy from Fu_Copy(:wstr, (:wpos + 1), 8191) into :wstr;--
STR resultante
r_ret = :r_ret || :wstr; --
Concateno o restante
wfez = 0; --
Para sair do LOOP
end
else begin --
Senão...
r_ret = :r_ret || :wdel || :tra1; --
concateno
select r_copy from Fu_Copy(:wstr, (:wpos + 1), 8191) into :wstr; --
STR resultante
end
end
end
end
end
else begin -- Orden Descending...
if (:tra1 < :wsub) then
r_ret = :wsub || :wdel || :wstr;
else begin
select r_last_pos from Fu_last_pos(:wdel, :wstr) into :wpos;
select r_copy from Fu_Copy(:wstr, (:wpos + 1), 8191) into :tra1;
if (:tra1 >= :wsub) then
r_ret = :wstr || :wdel || :wsub;
else begin
select result from Fu_pos(:wdel, :wstr) into :wpos;
select r_copy from Fu_Copy(:wstr, 1, (:wpos - 1)) into :tra1;
r_ret = :tra1 || :wdel;
select r_copy from Fu_Copy(:wstr, (:wpos + 1), 8191) into :wstr;
while (:wfez = 1) do begin
select result from Fu_pos(:wdel, :wstr) into :wpos;
if (:wpos = 0) then
tra1 = :wstr;
else
select r_copy from Fu_Copy(:wstr, 1, (:wpos - 1)) into :tra1;
if (:tra1 <= :wsub) then
begin
r_ret = :r_ret || :wsub || :wdel;
select r_copy from Fu_Copy(:wstr, (:wpos + 1), 8191) into :wstr;
r_ret = :r_ret || :wstr;
wfez = 0;
end
else begin
r_ret = :r_ret || :wdel || :tra1;
select r_copy from Fu_Copy(:wstr, (:wpos + 1), 8191) into :wstr;
end
end
end
end
end
suspend;
end
================================================
CREATE PROCEDURE FU_COPY(
WVAR VARCHAR(8192),
WINI INTEGER,
WTAM INTEGER)
RETURNS (
R_COPY VARCHAR(8192))
AS
DECLARE VARIABLE I INTEGER;
DECLARE VARIABLE J INTEGER;
DECLARE VARIABLE K INTEGER;
begin
/*
Copia de "WINI" "WTAM" bytes de "WVAR"
Este recurso não é mais necessário no FB 2
Pois já aceita o substring com variáveis
*/
select r_Len from Fu_Len(:wvar) into :i;
j = 1;
k = 1;
r_copy = '';
while ((:wvar is not null) and (:i > 0) and (j <= :wtam)) do begin
if (:k >= :wini) then begin
r_copy = :r_copy || substring(:wvar from 1 for 1);
j = j + 1;
end
wvar = substring(:wvar from 2 for 8191);
k = :k + 1;
i = :i - 1;
end
suspend;
end
========================================
CREATE PROCEDURE FU_CPA_PERI(
PER1 VARCHAR(8),
PER2 VARCHAR(8))
RETURNS (
R_CPA_PERI CHAR(1))
AS
begin
/*
Compara dois períodos (MM/AAAA) e devolve
"<", ">" ou "=" conforme o caso
*/
if ((:per1 is not null) and (:per2 is not null)) then begin
if ((substring(:per1 from 4 for 4) || substring(:per1 from 1 for
2)) =
(substring(:per2 from 4 for 4) || substring(:per2 from 1 for 2)))
then
r_cpa_peri = '=';
else if ((substring(:per1 from 4 for 4) || substring(:per1 from 1
for 2)) >
(substring(:per2 from 4 for 4) || substring(:per2 from 1 for 2)))
then
r_cpa_peri = '>';
else if ((substring(:per1 from 4 for 4) || substring(:per1 from 1
for 2)) <
(substring(:per2 from 4 for 4) || substring(:per2 from 1 for 2)))
then
r_cpa_peri = '<';
end
suspend;
end
===========================================
CREATE PROCEDURE FU_CRIP(
WSTR VARCHAR(1024),
ACAO SMALLINT)
RETURNS (
R_STR VARCHAR(1024))
AS
DECLARE VARIABLE WS1 VARCHAR(255);
DECLARE VARIABLE WS2 VARCHAR(255);
DECLARE VARIABLE WLT CHAR(1);
DECLARE VARIABLE WIN SMALLINT;
DECLARE VARIABLE WLE SMALLINT;
DECLARE VARIABLE WPO SMALLINT;
begin
/*
Devolve um string criptografado se "ACAO" = 0
senão descriptografa. Função bem CASEIRA
*/
ws1 = ' [AaB1bC2(c+Ç3çD4dE5eF6fG7g)H8hI9iJ0jKk-
LlMmNn]OoPpQqRrSsTtUuVvXxYyWwZz"!@#$%¨&*_´`{^~}|\<,>.:;?/' ||
'éóúàèìòùêûâîôÁÉÍÓÚÀÈÌÒÙÃÕ¥¡¢£¤¦§¨©ª®°±²³µ•¸¹"¼¾¿ÅÆÏÐÑÖ×ÝÞö÷øýþ';
ws2 = 'éóúàèìòùêûâîôÁÉÍÓÚÀÈÌÒÙÃÕ¥¡¢£¤¦§¨©ª®°±²³µ•¸¹"¼¾¿ÅÆÏÐÑÖ×ÝÞö÷øýþ'
||
'
AB0CÇ9DE8FG7HI6JK5LM4NO3PQ2RS1TUVXYWZabcçdefghijklmnopqrstuvxywz"!@#$%
¨&*()_+´`{[^~}]|\<,>.:;?/-';
r_str = '';
select r_Len from Fu_Len(:wstr) into :wle;
win = 1;
if (:acao = 0) then -- Criptografa a string
begin
while (:win <= :wle) do begin
select r_Copy from Fu_Copy(:wstr, :win, 1) into :wlt;
select result from Fu_Pos(:wlt, :ws1) into :wpo;
if (:wpo > 0) then
select r_Copy from Fu_Copy(:ws2, :wpo, 1) into :wlt;
r_str = :r_str || :wlt;
win = :win + 1;
end
end
else begin -- desfaz a criptografia
while (:win <= :wle) do begin
select r_Copy from Fu_Copy(:wstr, :win, 1) into :wlt;
select result from Fu_Pos(:wlt, :ws2) into :wpo;
if (:wpo > 0) then
select r_Copy from Fu_Copy(:ws1, :wpo, 1) into :wlt;
r_str = :r_str || :wlt;
win = :win + 1;
end
end
suspend;
end
=========================================
CREATE PROCEDURE FU_CUBE(
WNUM DOUBLE PRECISION)
RETURNS (
RAIZ DOUBLE PRECISION)
AS
declare variable parc double precision;
declare variable wraz smallint = 3;
begin
/*
Devolve a Raiz Cúbica de um número.
Há uma tolerância em caso de inexato.
*/
select sqr from Fu_sqrt(:wnum) into :parc;
while (:wraz > 2) do begin
select sqr from Fu_sqrt(:parc) into :raiz;
wraz = :wraz - 1;
end
wraz = 3;
parc = :raiz * raiz * :raiz;
while (:parc < :wnum) do begin
raiz = :raiz + 1;
parc = :raiz * raiz * :raiz;
end
if (:parc > :wnum) then begin
raiz = :raiz - 1;
parc = :raiz * raiz * :raiz;
while (:parc < :wnum) do begin
raiz = :raiz + 0.50000;
parc = :raiz * raiz * :raiz;
end
if (:parc > :wnum) then begin
raiz = :raiz - 0.50000;
parc = :raiz * raiz * :raiz;
while (:parc < :wnum) do begin
raiz = :raiz + 0.10000;
parc = :raiz * raiz * :raiz;
end
if (:parc > :wnum) then begin
raiz = :raiz - 0.250000;
parc = :raiz * raiz * :raiz;
while (:parc < :wnum) do begin
raiz = :raiz + 0.050000;
parc = :raiz * raiz * :raiz;
end
if (:parc > :wnum) then begin
raiz = :raiz - 0.050000;
parc = :raiz * raiz * :raiz;
while (:parc < :wnum) do begin
raiz = :raiz + 0.001000;
parc = :raiz * raiz * :raiz;
end
if (:parc > :wnum) then begin
raiz = :raiz - 0.0010000;
parc = :raiz * raiz * :raiz;
while (:parc < :wnum) do begin
raiz = :raiz + 0.0001000;
parc = :raiz * raiz * :raiz;
end
if (:parc > :wnum) then begin
raiz = :raiz - 0.00010000;
parc = :raiz * raiz * :raiz;
while (:parc < :wnum) do begin
raiz = :raiz + 0.00001000;
parc = :raiz * raiz * :raiz;
end
if (:parc > :wnum) then begin
raiz = :raiz - 0.000010000;
parc = :raiz * raiz * :raiz;
while (:parc < :wnum) do begin
raiz = :raiz + 0.000001000;
parc = :raiz * raiz * :raiz;
end
end
end
end
end
end
end
end
parc = cast(:raiz as integer);
if ((:parc * :parc * :parc) = :wnum) then
raiz = :parc;
suspend;
end
======================================
CREATE PROCEDURE FU_DATATELA(
DAT1 DATE,
DAT2 VARCHAR(24),
TIPO CHAR(1))
RETURNS (
DATA_TELA VARCHAR(19))
AS
begin
/*
Devolve uma data ou um TaimeStamp como:
DD/MM/YY ou DD/MM/YYYY ou
DD/MM/YY HH:MM:SS ou DD/MM/YYYY HH:MM:SS
como um string (Bom para relatórios)
*/
tipo = upper(:tipo);
if(:dat1 is not null) then
begin
if (:tipo = 'E') then
data_tela = substring(cast(:dat1 as varchar(10)) from 9 for 2) ||
'/' ||
substring(cast(:dat1 as varchar(10)) from 6 for 2) || '/' ||
substring(cast(:dat1 as varchar(10)) from 1 for 4);
else
data_tela = substring(cast(:dat1 as varchar(10)) from 9 for 2) ||
'/' ||
substring(cast(:dat1 as varchar(10)) from 6 for 2) || '/' ||
substring(cast(:dat1 as varchar(10)) from 2 for 2);
end
else begin
if (tipo = 'E') then
data_tela = substring(:dat2 from 9 for 2) || '/' ||
substring(:dat2 from 6 for 2) || '/' ||
substring(:dat2 from 1 for 4) || ' ' ||
substring(:dat2 from 12 for 8);
else
data_tela = substring(:dat2 from 9 for 2) || '/' ||
substring(:dat2 from 6 for 2) || '/' ||
substring(:dat2 from 2 for 2) || ' ' ||
substring(:dat2 from 12 for 8);
end
suspend;
end
================================================
CREATE PROCEDURE FU_DATE_TO_INTEGER(
WDAT CHAR(10))
RETURNS (
R_DTI INTEGER)
AS
declare variable wano smallint;
declare variable wmes smallint;
declare variable wdia smallint;
declare variable trab integer;
declare variable wmat integer;
begin
/*
Devolve um inteiro conforme a data informada
"WDAT" deve vir assim: aaaa-mm-dd
*/
wano = cast(substring(:wdat from 1 for 4) as smallint);
wmes = cast(substring(:wdat from 6 for 2) as smallint);
wdia = cast(substring(:wdat from 9 for 2) as smallint);
if (:wmes = 2) then wmat = 31;
else if (:wmes = 3) then wmat = 59;
else if (:wmes = 4) then wmat = 90;
else if (:wmes = 5) then wmat = 120;
else if (:wmes = 6) then wmat = 151;
else if (:wmes = 7) then wmat = 181;
else if (:wmes = 8) then wmat = 212;
else if (:wmes = 9) then wmat = 243;
else if (:wmes = 10) then wmat = 273;
else if (:wmes = 11) then wmat = 304;
else if (:wmes = 12) then wmat = 334;
else wmat = 0;
select r_abs from fu_abs(((:wano - 1901) * 366)) into :trab;
r_dti = :trab + :wmat + :wdia;
suspend;
end
============================================
CREATE PROCEDURE FU_DECIMAL_HORA(
FNUM DECIMAL(10,4))
RETURNS (
HORA VARCHAR(10),
WHOR INTEGER,
WMIN INTEGER)
AS
declare variable wint integer;
declare variable wtam integer;
declare variable trab varchar(14);
declare variable tra1 varchar(14);
begin
/*
Se "FNUM" = 10,50 então devolve 10,30... etc
Se "FNUM" = 15,20 então devolve 15,12
*/
select r_formatar from Fu_formatar(:fnum, '######0,0000') into
:trab;
select r_sright from Fu_s_right(:trab, 1) into
:tra1;
select r_ltrim from Fu_ltrim(:trab) into
:trab;
select r_len from Fu_len(:trab) into
:wtam;
while (:tra1 = '0') do begin
select r_sleft from Fu_s_left(:trab, :wtam - 1) into :trab;
select r_sright from Fu_s_right(:trab, 1) into :tra1;
wtam = :wtam - 1;
end
tra1 = :trab;
select result from Fu_pos(',', :trab) into :wint;
select r_copy from Fu_Copy(:trab, (:wint + 1), (:wtam - :wint)) into
:trab;
wmin = cast(:trab as integer);
wmin = :wmin * 6;
select r_div from Fu_div(:wmin, 10) into :wmin;
select r_copy from Fu_Copy(:tra1, 1, (:wint - 1)) into :trab;
whor = cast(:trab as integer);
while (:wmin > 60) do begin
wmin = :wmin - 60;
whor = :whor + 1;
end