Fórum Procedure com Returns #429614
24/11/2012
0
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
Curtir tópico
+ 0Posts
25/11/2012
Emerson Nascimento
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
Gostei + 0
25/11/2012
Márcio Lima
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?
Gostei + 0
25/11/2012
Claudia Nogueira
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.
Gostei + 0
25/11/2012
Márcio Lima
Grato
Gostei + 0
25/11/2012
Claudia Nogueira
Gostei + 0
25/11/2012
Márcio Lima
e no delphi não. Será que consegui te explicar?
grato
Gostei + 0
25/11/2012
Claudia Nogueira
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.
Gostei + 0
25/11/2012
Márcio Lima
eu estava executando a procedure por isso retornava com erro
e passando o select funcionou.
Gostei + 0
25/11/2012
Márcio Lima
Gostei + 0
25/11/2012
Claudia Nogueira
As vezes não consigo explicar direito.
Por isso quando eu começo responder, os tópicos ficam muito grandes.
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)