Como fazer para a procedure retornar um valor?

Firebird

08/04/2005

Criei a seguinte stored procedure:

CREATE PROCEDURE VLRJUROS (
    CLIENTE INTEGER,
    DUPLICATA VARCHAR(10) CHARACTER SET NONE)
RETURNS (
    VLRJUROS DOUBLE PRECISION)
AS
DECLARE VARIABLE VLR DOUBLE PRECISION;
begin
  for select ((data.data-mov_contareceberingresso.vencimento)*(mov_contareceberingresso.Valor*parametros.Juros_Dia/100))
  from mov_contareceberingresso, parametros, data where mov_contareceberingresso.Cliente = :cliente and
  mov_contareceberingresso.duplicata = :duplicata into :VLR do
  begin
  if (:VLR > 0) then
     vlrjuros = :VLR;
  else
     vlrjuros = 0;
  end
  suspend;
end


A minha intenção era executa-la em uma consulta para retornar o valor do juros das prestações do contas a receber. Tentei assim:

Select valor, vlrjuros(Cliente, Duplicata) from mov_Contareceberingresso


o resultado esperado por min seria o valor da prestação como na tabela e o vlr do juros calculado pela procedure.

É certo fazer desse modo?
O que está errado?
Dicas??????


Obrigado desde já


Marbravo

Marbravo

Curtidas 0

Respostas

Gandalf.nho

Gandalf.nho

08/04/2005

A SP aparentemente está certa, mas vc está passando os parâmetros de maneira errada na chamada. Faça assim

Select valor, vlrjuros from mov_Contareceberingresso(:Cliente, :Duplicata)


Substitua os parâmetros pelo valor desejado


GOSTEI 0
Marbravo

Marbravo

08/04/2005

Quando executo o codigo

Select valor, vlrjuros from mov_Contareceberingresso(:Cliente, :Duplicata)


da o seguinte erro:

ISC ERROR MESSAGE: Dynamic SQL Error SQL error code = -204 Procedure unknown MOV_CONTARECEBERINGRESSO At line 1, column 29. Statement: Select valor, vlrjuros from mov_Contareceberingresso(101367, ´280/A´)


Dicas???


GOSTEI 0
Gandalf.nho

Gandalf.nho

08/04/2005

Ops, agora que vi, sua SP está com nome diferente no que na linha de exemplo, deixa acertar aqui:

Select vlrjuros from VLRJUROS(:Cliente, :Duplicata)



GOSTEI 0
Marbravo

Marbravo

08/04/2005

Num deu certo ainda do jeito que eu quero....
Eu quero que ele calcule o juros de varios registro da consulta ai eu tentei assim:

Select CR.Duplicata, CR.Cliente, CR.Valor, j.vlrjuros from Mov_contareceberingresso CR, VLRJUROS(CR.Cliente, CR.Duplicata) j
where CR.valor >= 100


e deu o erro :
ISC ERROR MESSAGE:
no current record for fetch operation


Tentei tambei assim:

Select CR.Duplicata, CR.Cliente, CR.Valor, VLRJUROS(CR.Cliente, CR.Duplicata) from Mov_contareceberingresso CR
where CR.valor >= 100


deu o erro :

ISC ERROR MESSAGE:
Dynamic SQL Error
SQL error code = -804
Function unknown
VLRJUROS


I ai será que eu estou no caminho errado???
Quero que quando um cliente consulte algumas duplicatas as duplicatas já apareçam com o juros calculado.

Estou tentando, mas tá dificil...

Alguma dica???

Obrigado gandalf.nho
E ao demais que virem a ajudar.


GOSTEI 0
Gandalf.nho

Gandalf.nho

08/04/2005

Agora entendi, vc está tentando juntar a SP e tabelas normais numa só SELECT. Nunca tentei fazer isso, nem sei se dá. Não era mais fácil fazer a SP retornar logo todos os campos que vc deseja, como os dados do cliente?


GOSTEI 0
Marbravo

Marbravo

08/04/2005

Eu terminei a procedure, funcionou só que me veio a duvida
Se eu fizesse uma view talvez eu ganharia mais em velocidade e trabalho
ou a stored procedure é melhor...
ou eu troquei cebolas, poderia ter feito logo de principio uma view que daria a mesma coisa que a procedure????

Abaixo está o codigo da minha procedure :

CREATE PROCEDURE VLRJUROS 
RETURNS (
    VALOR_C_JUROS DOUBLE PRECISION,
    DIAS INTEGER,
    CLIENTE INTEGER,
    DUPLICATA VARCHAR(10) CHARACTER SET NONE,
    SERIE INTEGER,
    VENCIMENTO DATE,
    VALOR DOUBLE PRECISION,
    EMISSAO DATE,
    NOTA VARCHAR(10) CHARACTER SET NONE,
    LOJA_PAG INTEGER,
    VALOR_PAG DOUBLE PRECISION,
    DT_PAG DATE,
    TIPOPAG VARCHAR(10) CHARACTER SET NONE,
    PAGO VARCHAR(1) CHARACTER SET NONE,
    CAN VARCHAR(1) CHARACTER SET NONE,
    OBS VARCHAR(50) CHARACTER SET NONE,
    SERIEPEDIDO INTEGER,
    CONFIRMADO VARCHAR(1) CHARACTER SET NONE)
AS
DECLARE VARIABLE VLR DOUBLE PRECISION;
begin
  for select ((dt.data-cr.vencimento)*(cr.Valor*p.Juros_Dia/100)), (data.data-cr.vencimento), CLIENTE, DUPLICATA, SERIE,
  VENCIMENTO, VALOR, EMISSAO, NOTA, LOJA_PAG, VALOR_PAG, DT_PAG, tipopag, pago, can, obs, seriepedido, confirmado
  from mov_contareceberingresso CR, parametros P, data dt into :VLR, :dias, :CLIENTE, :DUPLICATA, :SERIE, :VENCIMENTO,
    :VALOR,
    :EMISSAO,
    :NOTA,
    :LOJA_PAG,
    :VALOR_PAG,
    :DT_PAG,
    :TIPOPAG,
    :PAGO,
    :CAN,
    :OBS,
    :SERIEPEDIDO,
    :CONFIRMADO do
  begin
      if (:VLR > 0) then
         VALOR_C_JUROS = :VLR;
      else
         VALOR_C_JUROS = 0;
  end
  suspend;
end



GOSTEI 0
Gandalf.nho

Gandalf.nho

08/04/2005

Acho que tanto faz, já que ambos são executados a partir do servidor. Eu, por exemplo, geralmente só uso SPs para SQLs mais complicadas impossíveis de serem feitas via view.


GOSTEI 0
Marbravo

Marbravo

08/04/2005

Agora que fui ver que minha procedure só tá retornando um registro...
Ai tentei fazer uma view realmente com a view é pior pelo fato de naum consequir fazer um if then para os resultados.

Mas por que só retorna um registro???

O codigo abaixo novamente:



CREATE PROCEDURE CR_JUROS 
RETURNS (
    VALOR_C_JUROS DOUBLE PRECISION,
    DIAS INTEGER,
    VLRJUROS DOUBLE PRECISION,
    CLIENTE INTEGER,
    DUPLICATA VARCHAR(10) CHARACTER SET NONE,
    SERIE INTEGER,
    VENCIMENTO DATE,
    VALOR DOUBLE PRECISION,
    EMISSAO DATE,
    NOTA VARCHAR(10) CHARACTER SET NONE,
    LOJA_PAG INTEGER,
    VALOR_PAG DOUBLE PRECISION,
    DT_PAG DATE,
    TIPOPAG VARCHAR(10) CHARACTER SET NONE,
    PAGO VARCHAR(1) CHARACTER SET NONE,
    CAN VARCHAR(1) CHARACTER SET NONE,
    OBS VARCHAR(50) CHARACTER SET NONE,
    SERIEPEDIDO INTEGER,
    CONFIRMADO VARCHAR(1) CHARACTER SET NONE)
AS
DECLARE VARIABLE VLR DOUBLE PRECISION;
begin
  for select (((dt.data-cr.vencimento)*(cr.Valor*p.Juros_Dia/100))+cr.Valor), (data.data-cr.vencimento), ((dt.data-cr.vencimento)*(cr.Valor*p.Juros_Dia/100)), CLIENTE, DUPLICATA, SERIE,
  VENCIMENTO, VALOR, EMISSAO, NOTA, LOJA_PAG, VALOR_PAG, DT_PAG, tipopag, pago, can, obs, seriepedido, confirmado
  from mov_contareceberingresso CR, parametros P, data dt into :VLR, :dias, :Vlrjuros, :CLIENTE, :DUPLICATA, :SERIE, :VENCIMENTO,
    :VALOR,
    :EMISSAO,
    :NOTA,
    :LOJA_PAG,
    :VALOR_PAG,
    :DT_PAG,
    :TIPOPAG,
    :PAGO,
    :CAN,
    :OBS,
    :SERIEPEDIDO,
    :CONFIRMADO do
  begin
      if (:dias > 0) then
         Begin
           VALOR_C_JUROS = :VLR;
           dias = :dias;
           vlrjuros = :vlrjuros;
         end
      else
         Begin
           VALOR_C_JUROS = 0;
           dias = null;
           vlrjuros = null;
         end
  end
  suspend;
end



GOSTEI 0
Gandalf.nho

Gandalf.nho

08/04/2005

Estava observando a sua SP e percebi que vc está usando 3 tabelas no SELECT mas não há um join entre elas.


GOSTEI 0
Marbravo

Marbravo

08/04/2005

Mudei minha procedure :

CREATE PROCEDURE CR_JUROS (
    JUROS_DIA DOUBLE PRECISION,
    DATADIA DATE)
RETURNS (
    VALOR_C_JUROS DOUBLE PRECISION,
    DIAS INTEGER,
    VLRJUROS DOUBLE PRECISION,
    CLIENTE INTEGER,
    DUPLICATA VARCHAR(10) CHARACTER SET NONE,
    SERIE INTEGER,
    VENCIMENTO DATE,
    VALOR DOUBLE PRECISION,
    EMISSAO DATE,
    NOTA VARCHAR(10) CHARACTER SET NONE,
    LOJA_PAG INTEGER,
    VALOR_PAG DOUBLE PRECISION,
    DT_PAG DATE,
    TIPOPAG VARCHAR(10) CHARACTER SET NONE,
    PAGO VARCHAR(1) CHARACTER SET NONE,
    CAN VARCHAR(1) CHARACTER SET NONE,
    OBS VARCHAR(50) CHARACTER SET NONE,
    SERIEPEDIDO INTEGER,
    CONFIRMADO VARCHAR(1) CHARACTER SET NONE)
AS
DECLARE VARIABLE VLR DOUBLE PRECISION;
begin
  for select (((:datadia-cr.vencimento)*(cr.Valor*:Juros_Dia/100))+cr.Valor), (:datadia-cr.vencimento), ((:datadia-cr.vencimento)*(cr.Valor*:Juros_Dia/100)), CLIENTE, DUPLICATA, SERIE,
  VENCIMENTO, VALOR, EMISSAO, NOTA, LOJA_PAG, VALOR_PAG, DT_PAG, tipopag, pago, can, obs, seriepedido, confirmado
  from mov_contareceberingresso CR into :VLR, :dias, :Vlrjuros, :CLIENTE, :DUPLICATA, :SERIE, :VENCIMENTO,
    :VALOR,
    :EMISSAO,
    :NOTA,
    :LOJA_PAG,
    :VALOR_PAG,
    :DT_PAG,
    :TIPOPAG,
    :PAGO,
    :CAN,
    :OBS,
    :SERIEPEDIDO,
    :CONFIRMADO do
  begin
      if (:dias > 0) then
         Begin
           VALOR_C_JUROS = :VLR;
           dias = :dias;
           vlrjuros = :vlrjuros;
         end
      else
         Begin
           VALOR_C_JUROS = 0;
           dias = null;
           vlrjuros = null;
         end
  end
  suspend;
end


Ainda está retornando apenas um registro o codigo a sequir funciona em uma consulta SQL comun mas na procedure retorna apenas um:

select (((:datadia-cr.vencimento)*(cr.Valor*:Juros_Dia/100))+cr.Valor), (:datadia-cr.vencimento), ((:datadia-cr.vencimento)*(cr.Valor*:Juros_Dia/100)), CLIENTE, DUPLICATA, SERIE,
  VENCIMENTO, VALOR, EMISSAO, NOTA, LOJA_PAG, VALOR_PAG, DT_PAG, tipopag, pago, can, obs, seriepedido, confirmado
  from mov_contareceberingresso CR 


I ai?????
Tá complicado...

t+


GOSTEI 0
Gandalf.nho

Gandalf.nho

08/04/2005

Experimente pôr o SUSPEND antes do penúltimo END, e não antes do último


GOSTEI 0
Afarias

Afarias

08/04/2005

sem levar em conta todo o tópico (q já está muito grande) só olhando para a mensagem original:

select valor,
(select campo_tal from vlrjuros(Cliente, Duplicata)) as campo_tal
from mov_Contareceberingresso


T+


GOSTEI 0
POSTAR