Fórum Procedure com Returns #429614

24/11/2012

0

Olá Pessoal, sou novato na área
gostaria que me ajudasse como executar uma procuedure com return no delphi
usando os componentes
SqlStoreProc dbexpress
DataSetProvider
ClientDataSet
DataSource
Firebird 2.1
delphi7

SEGUE A PROCUEDURE
create procedure CAIXA (
INICIO date,
FIM date)
returns (
DATA date,
RESUMO_MOV_MES varchar(50),
VALOR numeric(9,2),
SALDO numeric(9,2),
TIPO char(1),
HISTORICO VARCHAR(50))
as
declare variable SALDO_ANT_CREDITO numeric(9,2);
declare variable SALDO_ANT_DEBITO numeric(9,2);
BEGIN

/*Agora recuperamos a soma dos valores dos creditos anteriores ao
periodo informado*/
SELECT COALESCE(SUM(CX.VL_CREDITO),0)
FROM TB_CAIXA_TX_ADM CX
WHERE (CX.DT_MOV < :INICIO) AND (CX.TP_MOV = ''C'')
INTO :SALDO_ANT_CREDITO;

/*Primeiro recuperamos a soma dos valores dos debitos anteriores ao
periodo informado para posteriormente calcularmos nosso saldo inicial*/
SELECT COALESCE(SUM(CX.VL_DEBITO),0)
FROM TB_CAIXA_TX_ADM CX
WHERE (CX.DT_MOV < :INICIO) AND (CX.TP_MOV = ''D'')
INTO :SALDO_ANT_DEBITO;

/*Caso não haja lancamentos anteriores, a variavel ficara no estado NULL,
como no SQL qualquer operação matemática feita com valores NULL sempre
resulta em NULL, temos que verificar isso e atribuir 0.00 na variavel nula
para que forneça o resultado esperado. Isse será feito pela função COALESCE() */
DATA = :INICIO - 1;
RESUMO_MOV_MES = ''SALDO ANTERIOR'';
VALOR = 0;

/*Inicializando a variavel que armazenara o saldo final
com o valor do saldo anterior*/
SALDO = (SALDO_ANT_CREDITO - SALDO_ANT_DEBITO);

/*Por questões "estéticas" não queremos ter valores negativos no campo valor,
sendo assim, se o saldo anterior é negativo, devemos informar que o lançamento é
de débito e tornar o valor do saldo positivo, caso contratio informamos que o
lançamento é de crédito.*/
IF (:VALOR < 0) THEN
BEGIN
TIPO = ''D'';
VALOR = VALOR * -1;
END
ELSE
TIPO = ''C'';

SUSPEND; /*Retornando a primeira linha (registro) com o saldo anterior
o comando a seguir seleciona os registros dentro do periodo informado
buscando na tabela de contas a pagar*/

DATA = :INICIO;
WHILE (:DATA <= :FIM) DO
BEGIN
TIPO = ''D''; /*Estamos recuperando débitos*/
FOR SELECT CX.DT_MOV, CX.DESCRICAO,CX.NR_DOC, CX.VL_DEBITO
FROM TB_CAIXA_TX_ADM CX
WHERE (CX.DT_MOV = :DATA)
AND (CX.TP_MOV = ''D'')
AND COALESCE(CX.VL_DEBITO,0) > 0
INTO :DATA, :HISTORICO, :RESUMO_MOV_MES, :VALOR
DO
BEGIN
/*Subtraimos o valor do lançamento do saldo final*/
RESUMO_MOV_MES = :RESUMO_MOV_MES;
VALOR = :VALOR;
SALDO = SALDO - VALOR;

/*O suspend a seguir retorna uma "linha" contendo os campos
data, historico, tipo e valor que tem seus valores armazenados
nas variáveis de mesmo nome*/
SUSPEND;
END

TIPO = ''C''; /*Estamos recuperando créditos*/
/*seleciona os registros dentro do periodo informado
buscando na tabela de contas a receber*/
FOR SELECT CX.DT_MOV, CX.DESCRICAO, CX.NR_DOC, CX.VL_CREDITO
FROM TB_CAIXA_TX_ADM CX
WHERE (CX.DT_MOV = :DATA)
AND (CX.TP_MOV = ''C'')
AND COALESCE(CX.VL_CREDITO,0) > 0
INTO :DATA, :HISTORICO, :RESUMO_MOV_MES, :VALOR
DO
BEGIN
/*Adicionamos o valor do lançamento ao saldo final*/
SALDO = SALDO + VALOR;
RESUMO_MOV_MES = :RESUMO_MOV_MES;
VALOR = :VALOR;

/*O suspend a seguir retorna uma "linha" contendo os campos
data, historico, tipo e valor que tem seus valores armazenados
nas variáveis de mesmo nome*/
SUSPEND;
END

DATA = DATA + 1;
END

/*Montamos o ultimo "registro" que conterá os valores do saldo FINAL*/
IF (:SALDO < 0) THEN
BEGIN
TIPO = ''D'';
SALDO = SALDO * -1;
END
ELSE
TIPO = ''C'';

DATA = :FIM;
RESUMO_MOV_MES = ''SALDO FINAL'';
VALOR = 0;
SUSPEND;
END

GOSTARIA QUE RETORNASSE ESTE CAMPOS
DATA
RESUMO_MOV_MES
VALOR
SALDO
TIPO
HISTORICO
NO DATASOURCE
RETORNA VAZIO O QUE FAÇO?
GRATO A TODOS QUE COLABORAREM
Márcio Lima

Márcio Lima

Responder

Posts

25/11/2012

Emerson Nascimento

tente com esta versão. note que fiz apenas duas alterações:
1. para melhorar a performance, faço o cálculo dos débitos e dos créditos numa única instrução.
2. atribuí corretamente o conteúdo da variável VALOR.

create procedure CAIXA (
    INICIO date,
    FIM date) 
returns (
    DATA date,
    RESUMO_MOV_MES varchar(50),
    VALOR numeric(9,2),
    SALDO numeric(9,2),
    TIPO char(1),
    HISTORICO VARCHAR(50))
as
declare variable SALDO_ANT_CREDITO numeric(9,2);
declare variable SALDO_ANT_DEBITO numeric(9,2);
BEGIN

    /*Agora recuperamos a soma dos valores dos creditos e dos debitos anteriores
     ao periodo informado, para posteriormente calcularmos nosso saldo inicial*/
    SELECT  SUM(CASE WHEN CX.TP_MOV = 'C' THEN COALESCE(CX.VL_CREDITO,0) ELSE 0 END),
            SUM(CASE WHEN CX.TP_MOV = 'D' THEN COALESCE(CX.VL_DEBITO,0)  ELSE 0 END)
    FROM TB_CAIXA_TX_ADM CX
    WHERE (CX.DT_MOV < :INICIO)
    INTO :SALDO_ANT_CREDITO, :SALDO_ANT_DEBITO;

    /*Caso nao haja lancamentos anteriores, a variavel ficara no estado NULL,
    como no SQL qualquer operacao matematica feita com valores NULL sempre
    resulta em NULL, temos que verificar isso e atribuir 0.00 na variavel nula
    para que forneca o resultado esperado. Isso sera feito pela funcao COALESCE() */
    DATA = :INICIO - 1;
    RESUMO_MOV_MES = 'SALDO ANTERIOR';

    /*Inicializando a variavel que armazenara o saldo final
    com o valor do saldo anterior*/
    SALDO = (COALESCE(SALDO_ANT_CREDITO,0) - COALESCE(SALDO_ANT_DEBITO,0));
    VALOR = SALDO;

    /*Por questoes "esteticas" nao queremos ter valores negativos no campo valor,
    sendo assim, se o saldo anterior for negativo, devemos informar que o lancamento eh
    de debito e tornar o valor do saldo positivo, caso contrario informamos que o
    lancamento eh de credito.*/
    IF (:VALOR < 0) THEN
    BEGIN
        TIPO = 'D';
        VALOR = VALOR * -1;
    END
    ELSE
        TIPO = 'C';

    SUSPEND; /*Retornando a primeira linha (registro) com o saldo anterior
                o comando a seguir seleciona os registros dentro do periodo informado
                buscando na tabela de contas a pagar*/

    DATA = :INICIO;
    WHILE (:DATA <= :FIM) DO
    BEGIN
        TIPO = 'D'; /*Estamos recuperando debitos*/
        FOR SELECT CX.DT_MOV, CX.DESCRICAO, CX.NR_DOC, CX.VL_DEBITO
            FROM TB_CAIXA_TX_ADM CX
            WHERE (CX.DT_MOV = :DATA)
            AND (CX.TP_MOV = 'D')
            AND COALESCE(CX.VL_DEBITO,0) > 0
            INTO :DATA, :HISTORICO, :RESUMO_MOV_MES, :VALOR
        DO
        BEGIN
            /*Subtraimos o valor do lancamento do saldo final*/
            SALDO = SALDO - VALOR;

            /*O suspend a seguir retorna uma "linha" contendo os campos
            data, historico, tipo e valor que tem seus valores armazenados
            nas variaveis de mesmo nome*/
            SUSPEND;
        END

        TIPO = 'C'; /*Estamos recuperando creditos*/
                    /*seleciona os registros dentro do periodo informado
                    buscando na tabela de contas a receber*/
        FOR SELECT CX.DT_MOV, CX.DESCRICAO, CX.NR_DOC, CX.VL_CREDITO
            FROM TB_CAIXA_TX_ADM CX
            WHERE (CX.DT_MOV = :DATA)
            AND (CX.TP_MOV = 'C')
            AND COALESCE(CX.VL_CREDITO,0) > 0
            INTO :DATA, :HISTORICO, :RESUMO_MOV_MES, :VALOR
        DO
        BEGIN
            /*Adicionamos o valor do lancamento ao saldo final*/
            SALDO = SALDO + VALOR;

            /*O suspend a seguir retorna uma "linha" contendo os campos
            data, historico, tipo e valor que tem seus valores armazenados
            nas variaveis de mesmo nome*/
            SUSPEND;
        END

        DATA = DATA + 1;
    END

    /*Montamos o ultimo "registro" que contera os valores do saldo FINAL*/
    IF (:SALDO < 0) THEN
    BEGIN
        TIPO = 'D';
        SALDO = SALDO * -1;
    END
    ELSE
        TIPO = 'C';

    DATA = :FIM;
    RESUMO_MOV_MES = 'SALDO FINAL';
    VALOR = 0;

    SUSPEND;
END
Responder

Gostei + 0

25/11/2012

Márcio Lima

Emerson Obrigado Pela Dica. Mais acho que não expliquei melhor o que eu quero.
O que eu quero é executar esta procedure no delphi passando os parametros Inicio e Fin
e ao executar me mostrar o resultado em um DataSource.
Entendeu?
Responder

Gostei + 0

25/11/2012

Claudia Nogueira

Não sou muito expert no assunto, mas como quase ninguém respondeu vou tentar ajudar.
Você criou uma procedure selecionável, então você não pode usar o SqlStoreProc e sim o SQLQuery.

Teria que ligar o DataSetProvider no SQLQuery e marcar a opção poAllowCommandText do DataSetProvider = True.
Feito isso você liga o ClienteDataSet no DataSetProvider e onde você quiser executar você faria mais ou menos assim:

ClientDataSet1.Close;
ClientDataSet1.CommandText := 'SELECT * FROM CAIXA(:INICIO,:FIM)';
ClientDataSet1.Params[0].AsDateTime := DataInicial;
ClientDataSet1.Params[1].AsDateTime := DataFinal;
ClientDataSet1.Open;



Algumas pessoas podem criticar essa forma, mas é a única que eu sei.
Se não servir, aí posta novamente que alguém com mais conhecimento provavelmente vai te ajudar.
Responder

Gostei + 0

25/11/2012

Márcio Lima

Amiga. Obrigado por tentar me ajudar mas nas resolveu o meu problema.
Grato
Responder

Gostei + 0

25/11/2012

Claudia Nogueira

Hum que pena, mas fala por que não fumciou. Antes de responder eu testei.
Responder

Gostei + 0

25/11/2012

Márcio Lima

Não me retornou como queria, se você executar a procedure no banco de dados me retorna como eu quero,
e no delphi não. Será que consegui te explicar?
grato
Responder

Gostei + 0

25/11/2012

Claudia Nogueira

Eu entendi o que você quer, mas olha só, quando uma procedure do Firebird tem que retornar algum valor você não usa:

EXECUTE PROCEDURE CAIXA(:INICIO,:FIM)


e sim:

SELECT * FROM CAIXA(:INICIO,:FIM)


Estou me baseando que a procedure se chama CAIXA conforme você postou.

Faz direto no banco de dados esses dois procedimentos e veja a diferença.
Enquanto o EXECUTE PROCEDURE retorna algo como:

------ Procedure executing results: ------
Resultado

O SELECT * FROM CAIXA(:INICIO,:FIM) retorna realmente as linhas.

Por isso ao usar o SQLQuery no lugar do SQLStoredProc1.
Responder

Gostei + 0

25/11/2012

Márcio Lima

Amiga show de bola viu, funcionou legal.
eu estava executando a procedure por isso retornava com erro
e passando o select funcionou.
Responder

Gostei + 0

25/11/2012

Márcio Lima

MUITO OBRIGADO VIU!!!
Responder

Gostei + 0

25/11/2012

Claudia Nogueira

Fico feliz!
As vezes não consigo explicar direito.
Por isso quando eu começo responder, os tópicos ficam muito grandes.

MUITO OBRIGADO VIU!!!
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar