Procedure com Returns
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
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
Curtidas 0
Respostas
Emerson Nascimento
24/11/2012
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.
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
Márcio Lima
24/11/2012
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?
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
Claudia Nogueira
24/11/2012
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:
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.
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
Márcio Lima
24/11/2012
Amiga. Obrigado por tentar me ajudar mas nas resolveu o meu problema.
Grato
Grato
GOSTEI 0
Claudia Nogueira
24/11/2012
Hum que pena, mas fala por que não fumciou. Antes de responder eu testei.
GOSTEI 0
Márcio Lima
24/11/2012
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
e no delphi não. Será que consegui te explicar?
grato
GOSTEI 0
Claudia Nogueira
24/11/2012
Eu entendi o que você quer, mas olha só, quando uma procedure do Firebird tem que retornar algum valor você não usa:
e sim:
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.
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
Márcio Lima
24/11/2012
Amiga show de bola viu, funcionou legal.
eu estava executando a procedure por isso retornava com erro
e passando o select funcionou.
eu estava executando a procedure por isso retornava com erro
e passando o select funcionou.
GOSTEI 0
Márcio Lima
24/11/2012
MUITO OBRIGADO VIU!!!
GOSTEI 0
Claudia Nogueira
24/11/2012
Fico feliz!
As vezes não consigo explicar direito.
Por isso quando eu começo responder, os tópicos ficam muito grandes.
As vezes não consigo explicar direito.
Por isso quando eu começo responder, os tópicos ficam muito grandes.
MUITO OBRIGADO VIU!!!
GOSTEI 0