Problema com SP executável
Criei uma SP simples do tipo executável para fazer umas totalizações da base de dados. São 4 linhas do tipo SELECT SUM(campo) FROM tabela WHERE ... INTO e no final um somatório envolvendo o resultado de cada select. O estranho é que se uso EXECUTE PROCEDURE a SP retorna os dois parâmetros de saída em branco. Se eu coloco SUSPEND no fim da SP e uso SELECT, funciona direito. Alguém sabe o pq disso, já que a SP deveria ser executável e não selecionável? Inclusive já fiz procedures semelhantes no passado e sempre funcionaram certo, só essa não está dando... O banco foi criado em IB 6 mas agora foi migrado para FB 1.5 (mas já não funcionava antes). Em tempo, cada um dos SELECTS individuais que compõem a SP foi testado individualmente e retornavam o resultado correto. Se não conseguir resolver isso, vou ter que trocar meu IBStoredProc por um IBQuery.
Gandalf.nho
Curtidas 0
Respostas
Alexrol
28/10/2004
Ola colega
Post sua Sp aqui para que fique mais facil de resolver
Post sua Sp aqui para que fique mais facil de resolver
GOSTEI 0
Gandalf.nho
28/10/2004
CREATE PROCEDURE ´CALCULA_MOVIMENTOS´
(
PCDEQUIPAMENTO INTEGER
)
RETURNS
(
TOTALESTOQUE DOUBLE PRECISION,
TOTALEMPRESTIMOS DOUBLE PRECISION
)
AS
declare variable vSomaEntrada DOUBLE PRECISION;
declare variable vSomaSaida DOUBLE PRECISION;
declare variable vSomaDevolucoes DOUBLE PRECISION;
BEGIN
vSomaEntrada = 0;
vSomaSaida = 0;
SELECT SUM(QTDMOVIMENTO) FROM MOVIMENT
WHERE CDEQUIPAMENTO = :´PCDEQUIPAMENTO´ AND TPMOVIMENTO = ´E´
INTO :vSomaEntrada;
SELECT SUM(QTDMOVIMENTO) FROM MOVIMENT
WHERE CDEQUIPAMENTO = :´PCDEQUIPAMENTO´ AND TPMOVIMENTO = ´S´
INTO :vSomaSaida;
SELECT SUM(QTDMOVIMENTO) FROM MOVIMENT
WHERE CDEQUIPAMENTO = :´PCDEQUIPAMENTO´ AND TPMOVIMENTO = ´A´
INTO :TOTALEMPRESTIMOS;
SELECT SUM(QTDMOVIMENTO) FROM MOVIMENT
WHERE CDEQUIPAMENTO = :´PCDEQUIPAMENTO´ AND TPMOVIMENTO = ´D´
INTO :vSomaDevolucoes;
TOTALESTOQUE = (vSomaEntrada + vSomaDevolucoes) - (vSomaSaida + TOTALEMPRESTIMOS);
END
(
PCDEQUIPAMENTO INTEGER
)
RETURNS
(
TOTALESTOQUE DOUBLE PRECISION,
TOTALEMPRESTIMOS DOUBLE PRECISION
)
AS
declare variable vSomaEntrada DOUBLE PRECISION;
declare variable vSomaSaida DOUBLE PRECISION;
declare variable vSomaDevolucoes DOUBLE PRECISION;
BEGIN
vSomaEntrada = 0;
vSomaSaida = 0;
SELECT SUM(QTDMOVIMENTO) FROM MOVIMENT
WHERE CDEQUIPAMENTO = :´PCDEQUIPAMENTO´ AND TPMOVIMENTO = ´E´
INTO :vSomaEntrada;
SELECT SUM(QTDMOVIMENTO) FROM MOVIMENT
WHERE CDEQUIPAMENTO = :´PCDEQUIPAMENTO´ AND TPMOVIMENTO = ´S´
INTO :vSomaSaida;
SELECT SUM(QTDMOVIMENTO) FROM MOVIMENT
WHERE CDEQUIPAMENTO = :´PCDEQUIPAMENTO´ AND TPMOVIMENTO = ´A´
INTO :TOTALEMPRESTIMOS;
SELECT SUM(QTDMOVIMENTO) FROM MOVIMENT
WHERE CDEQUIPAMENTO = :´PCDEQUIPAMENTO´ AND TPMOVIMENTO = ´D´
INTO :vSomaDevolucoes;
TOTALESTOQUE = (vSomaEntrada + vSomaDevolucoes) - (vSomaSaida + TOTALEMPRESTIMOS);
END
GOSTEI 0
Afarias
28/10/2004
note q se ::
SELECT SUM(QTDMOVIMENTO) FROM MOVIMENT
WHERE CDEQUIPAMENTO = :´PCDEQUIPAMENTO´
AND TPMOVIMENTO = ´A´
INTO :TOTALEMPRESTIMOS;
retornar NULO então ::
TOTALESTOQUE = (vSomaEntrada + vSomaDevolucoes) - (vSomaSaida + TOTALEMPRESTIMOS);
Será NULO também!
então, antes do cálculo faça ::
if (TOTALEMPRESTIMOS IS NULL) then
TOTALEMPRESTIMOS = 0;
o mesmo para todas as outras variáveis q entam no cálculo.
Outra coisa, pq o parâmetro PCDEQUIPAMENTO está sendo usando entre aspas???
T+
SELECT SUM(QTDMOVIMENTO) FROM MOVIMENT
WHERE CDEQUIPAMENTO = :´PCDEQUIPAMENTO´
AND TPMOVIMENTO = ´A´
INTO :TOTALEMPRESTIMOS;
retornar NULO então ::
TOTALESTOQUE = (vSomaEntrada + vSomaDevolucoes) - (vSomaSaida + TOTALEMPRESTIMOS);
Será NULO também!
então, antes do cálculo faça ::
if (TOTALEMPRESTIMOS IS NULL) then
TOTALEMPRESTIMOS = 0;
o mesmo para todas as outras variáveis q entam no cálculo.
Outra coisa, pq o parâmetro PCDEQUIPAMENTO está sendo usando entre aspas???
T+
GOSTEI 0
Gandalf.nho
28/10/2004
note q se ::
SELECT SUM(QTDMOVIMENTO) FROM MOVIMENT
WHERE CDEQUIPAMENTO = :´PCDEQUIPAMENTO´
AND TPMOVIMENTO = ´A´
INTO :TOTALEMPRESTIMOS;
retornar NULO então ::
TOTALESTOQUE = (vSomaEntrada + vSomaDevolucoes) - (vSomaSaida + TOTALEMPRESTIMOS);
Será NULO também!
então, antes do cálculo faça ::
if (TOTALEMPRESTIMOS IS NULL) then
TOTALEMPRESTIMOS = 0;
o mesmo para todas as outras variáveis q entam no cálculo.
Outra coisa, pq o parâmetro PCDEQUIPAMENTO está sendo usando entre aspas???
T+
Eu já tentei isso do IS NULL, mas mesmo assim não funciona. Inclusive os
parâmetros de saída não saem com valor NULO e sim em branco, como se a SP não estivesse sendo executada. Quanto as aspas do parâmetro, isso é por causa do recurso de visualizar metadata do IBOConsole, que insiste em mostrar assim, mesmo eu criando as SP sem usar aspas.
GOSTEI 0
Afarias
28/10/2004
e como exatamente vc está executando este procedimento?
e em q ferremanta??
T+
e em q ferremanta??
T+
GOSTEI 0
Gandalf.nho
28/10/2004
Estou testando no próprio IBOConsole, usando EXECUTE PROCEDURE
GOSTEI 0
Afarias
28/10/2004
Como havia pensado! O erro não está no Procedimento ou no IB/FB -- está no IBOConsole!
Vc poderia ter testado em seu sistema ou no IBConsole e veria q o resultado aparece.
:D
T+
Vc poderia ter testado em seu sistema ou no IBConsole e veria q o resultado aparece.
:D
T+
GOSTEI 0
_chiappone_
28/10/2004
note q se ::
SELECT SUM(QTDMOVIMENTO) FROM MOVIMENT
WHERE CDEQUIPAMENTO = :´PCDEQUIPAMENTO´
AND TPMOVIMENTO = ´A´
INTO :TOTALEMPRESTIMOS;
retornar NULO então ::
TOTALESTOQUE = (vSomaEntrada + vSomaDevolucoes) - (vSomaSaida + TOTALEMPRESTIMOS);
Será NULO também!
então, antes do cálculo faça ::
if (TOTALEMPRESTIMOS IS NULL) then
TOTALEMPRESTIMOS = 0;
o mesmo para todas as outras variáveis q entam no cálculo.
Outra coisa, pq o parâmetro PCDEQUIPAMENTO está sendo usando entre aspas???
T+
Colega, soh uma coisinha... se o gandalf estah usando FB 1.5, ele pode usar o comando coalesce, assim ele nao teria problemas com null
SELECT Coalesce(SUM(QTDMOVIMENTO), 0) FROM MOVIMENT WHERE CDEQUIPAMENTO = :"PCDEQUIPAMENTO" AND TPMOVIMENTO = ´A´ INTO :TOTALEMPRESTIMOS;
Sintaxe do coalesce:
Coalesce(<campo>,<valor se null>)
Outra coisa... ateh onde eu sei, pra vc poder exibir algum resultado na sua procedure, vc deve usar o comando
suspend;
sem ele, vc naum concluiu ao firebird que a procedure estah terminada e que voce pode ver os resultados.
Fiz um teste com uma procedure minha agora, retirando o suspend e
ela também parou de funcionar.
Experimente colocar o suspend e os coalesces assim, assim:
CREATE PROCEDURE "CALCULA_MOVIMENTOS" ( PCDEQUIPAMENTO INTEGER ) RETURNS ( TOTALESTOQUE DOUBLE PRECISION, TOTALEMPRESTIMOS DOUBLE PRECISION ) AS declare variable vSomaEntrada DOUBLE PRECISION; declare variable vSomaSaida DOUBLE PRECISION; declare variable vSomaDevolucoes DOUBLE PRECISION; BEGIN vSomaEntrada = 0; vSomaSaida = 0; SELECT coalesce(SUM(QTDMOVIMENTO),0) FROM MOVIMENT WHERE CDEQUIPAMENTO = :"PCDEQUIPAMENTO" AND TPMOVIMENTO = ´E´ INTO :vSomaEntrada; SELECT coalesce(SUM(QTDMOVIMENTO),0) FROM MOVIMENT WHERE CDEQUIPAMENTO = :"PCDEQUIPAMENTO" AND TPMOVIMENTO = ´S´ INTO :vSomaSaida; SELECT coalesce(SUM(QTDMOVIMENTO),0) FROM MOVIMENT WHERE CDEQUIPAMENTO = :"PCDEQUIPAMENTO" AND TPMOVIMENTO = ´A´ INTO :TOTALEMPRESTIMOS; SELECT coalesce(SUM(QTDMOVIMENTO),0) FROM MOVIMENT WHERE CDEQUIPAMENTO = :"PCDEQUIPAMENTO" AND TPMOVIMENTO = ´D´ INTO :vSomaDevolucoes; TOTALESTOQUE = (vSomaEntrada + vSomaDevolucoes) - (vSomaSaida + TOTALEMPRESTIMOS); Suspend; END
Espero que tenha ajudado!
GOSTEI 0
Afarias
28/10/2004
|Colega, soh uma coisinha... se o gandalf estah usando FB 1.5, ele pode
Não é ELE... é [color=red:8e8551e865][b:8e8551e865]ELA[/b:8e8551e865][/color:8e8551e865]!!!!
;)
|Outra coisa... ateh onde eu sei, pra vc poder exibir algum resultado na
|sua procedure, vc deve usar o comando suspend
só em procedimentos ´selecionáveis´ -- mas ela deseja um procedimento ´executável´
|Fiz um teste com uma procedure minha agora, retirando o suspend e
|ela também parou de funcionar.
pq vc está usando ´select * from procedimento´
faça ´execute procedure procedimento´ e receberá o resultado (1 apenas)
T+
Não é ELE... é [color=red:8e8551e865][b:8e8551e865]ELA[/b:8e8551e865][/color:8e8551e865]!!!!
;)
|Outra coisa... ateh onde eu sei, pra vc poder exibir algum resultado na
|sua procedure, vc deve usar o comando suspend
só em procedimentos ´selecionáveis´ -- mas ela deseja um procedimento ´executável´
|Fiz um teste com uma procedure minha agora, retirando o suspend e
|ela também parou de funcionar.
pq vc está usando ´select * from procedimento´
faça ´execute procedure procedimento´ e receberá o resultado (1 apenas)
T+
GOSTEI 0
Gandalf.nho
28/10/2004
Você falou para testar em outro lugar, mas no meu sistema tb não dá certo e o IBConsole não funciona com o FB 1.5
GOSTEI 0
Afarias
28/10/2004
Estranho q no seu sistema nào funcione. Qual o comportamento no seu sistema??
Outro lugar onde vc pode testar é no IBExpert -- é uma ferramenta muito boa.
T+
Outro lugar onde vc pode testar é no IBExpert -- é uma ferramenta muito boa.
T+
GOSTEI 0
Gandalf.nho
28/10/2004
O comportamento no meu sistema é o mesmo, não retorna nada. Acho que vou ter que deixar como selecionável mesmo e usar um IBQuery para pegar os dados
GOSTEI 0
Vinicius2k
28/10/2004
gandalf,
Assumidamente SPs e Triggers não são meu forte, mas como vc está desistindo, vou arriscar...
Consegui simular seu erro... se a tabela estiver povoada de forma que todas as variáveis recebam algum valor, funciona bem, mas se alguma das variáveis for NULL então, o retorno do parametro em que a variável NULL estiver envolvida também é NULL...
Criei uma tabela assim :
E modifiquei sua procedure assim :
Desta forma esta funcionando adequadamente, tanto no IBExpert quando dentro da aplicação (IBStoredProc)...
Acho q seu problema é com as variáveis NULL, assim como o Anderson já havia levantado...
Espero ter ajudado...
T+
Assumidamente SPs e Triggers não são meu forte, mas como vc está desistindo, vou arriscar...
Consegui simular seu erro... se a tabela estiver povoada de forma que todas as variáveis recebam algum valor, funciona bem, mas se alguma das variáveis for NULL então, o retorno do parametro em que a variável NULL estiver envolvida também é NULL...
Criei uma tabela assim :
create table MOVIMENT ( IDMOVIMENTO integer not null, CDEQUIPAMENTO integer, TPMOVIMENTO char(1), QTDMOVIMENTO numeric(15,2), constraint PK_MOVIMENT primary key (IDMOVIMENTO) );
E modifiquei sua procedure assim :
create procedure CALCULA_MOVIMENTOS ( PCDEQUIPAMENTO integer ) returns ( TOTALESTOQUE double precision, TOTALEMPRESTIMOS double precision ) as declare variable SOMAENTRADA double precision; declare variable SOMASAIDA double precision; declare variable SOMADEVOLUCOES double precision; begin select sum(QTDMOVIMENTO) from MOVIMENT where CDEQUIPAMENTO = :PCDEQUIPAMENTO and TPMOVIMENTO = ´E´ into :SOMAENTRADA; /****/ select sum(QTDMOVIMENTO) from MOVIMENT where CDEQUIPAMENTO = :PCDEQUIPAMENTO and TPMOVIMENTO = ´S´ into :SOMASAIDA; /****/ select sum(QTDMOVIMENTO) from MOVIMENT where CDEQUIPAMENTO = :PCDEQUIPAMENTO and TPMOVIMENTO = ´D´ into :SOMADEVOLUCOES; /****/ select sum(QTDMOVIMENTO) from MOVIMENT where CDEQUIPAMENTO = :PCDEQUIPAMENTO and TPMOVIMENTO = ´A´ into :TOTALEMPRESTIMOS; /****/ if (SOMAENTRADA is null) then SOMAENTRADA = 0; if (SOMASAIDA is null) then SOMASAIDA = 0; if (SOMADEVOLUCOES is null) then SOMADEVOLUCOES = 0; if (TOTALEMPRESTIMOS is null) then TOTALEMPRESTIMOS = 0; /****/ TOTALESTOQUE = (SOMAENTRADA + SOMADEVOLUCOES) - (SOMASAIDA + TOTALEMPRESTIMOS); end
Desta forma esta funcionando adequadamente, tanto no IBExpert quando dentro da aplicação (IBStoredProc)...
Acho q seu problema é com as variáveis NULL, assim como o Anderson já havia levantado...
Espero ter ajudado...
T+
GOSTEI 0
Gandalf.nho
28/10/2004
Agradeço a ajuda, mas como já tinha falado acima, já tinha tentado esse esquema do IS NULL e agora tentei até COALESCE sem resultado. A questão é que nem nulo retorna os parâmetros, não retorna nada, como se a procedure nem sequer executassse...
Acabei desistindo de fazer ela funcionar como SP executável, coloquei um SUSPEND e vou usar SELECT FROM procedure mesmo. Obrigada a quem tentou ajudar.
Acabei desistindo de fazer ela funcionar como SP executável, coloquei um SUSPEND e vou usar SELECT FROM procedure mesmo. Obrigada a quem tentou ajudar.
GOSTEI 0