Criar PROCEDURE para somar campos na tabela

Delphi

13/10/2008

Gente

como eu faço uma procedure para somar 4 campos da tabela e gravar o resultado num campo TOTAL da mesma tabela no mesmo registro? Mas só pode gravar quando for um REGISTRO NOVO ou for alterado qualquer valor dos 4 campos.

Assim

SALARIO1,SALARIO2,SALARIO3,SALARIO4 soma e salva em TOTALSALARIO.

Obrigado turma!


Klr2

Klr2

Curtidas 0

Respostas

Klr2

Klr2

13/10/2008

Esquici de dizer: uso o firebird 2.1


GOSTEI 0
Klr2

Klr2

13/10/2008

Gente depois de pesquisar muito cheguei a isso, mas só funciona quando o registro é novo. Quando insiro um valor num registro já existente nao soma nada :cry:


SET SQL DIALECT 3;

SET NAMES WIN1252;


SET TERM ^ ;


CREATE OR ALTER TRIGGER SOMANOTAS_IN FOR BOLETIM
ACTIVE AFTER INSERT POSITION 0
AS
begin
UPDATE FUNCIONARIOS SET TOTALSALARIOS = MES1 + MES2 + MES3 + MES4 + MES5 + MES6 + MES7 + MES8 + MES9 + MES10 + MES11 + MES12 where codigo = new.codigo;
end
^


SET TERM ; ^


GOSTEI 0
Joaoshi

Joaoshi

13/10/2008

Colega, por que não cria um campo calculado na TABELA ?


GOSTEI 0
Klr2

Klr2

13/10/2008

amigo joaoshi eu tentei isso já, mas dá um erro na minha aplicação quando tento usar esse campo calculado para mostrar na tela ou relatórios, daí pensei que seria mais fácil criar uma trigger que somasse os valores a medida que são inseridos/alterados. Mas sou novato na linguagem/banco de dados e tou quebrando muito a cabeça e não consigo uma solução. As teorias eu até que tenho o que me falta é saber como e onde aplicá-las. Em resumo, EU NÂO SEI fazer mesmo.
Obrigado pela dica de qualquer forma.


GOSTEI 0
.lg.

.lg.

13/10/2008

tente assim:
var
  total: Integer;

total := 0;

with SeuaTabelaouAdq do begin
  First;
  while not EoF do begin
    total := total + Int(SeuField.value) //coloquei o int para tirar a parte inteira dele.
  end;
end;


Espero que funcione.
A ideia é usar o EoF para percorrer sua tabela. porem vc atribui a variavel o valor do campo que deseja. Ele vai passar por cadainha da tabela.

Se n ajudar poste aí. :wink:


GOSTEI 0
Klr2

Klr2

13/10/2008

Amigo .lg.

Valeu pela dica... mas acho que voce nao compreendeu :wink: Nao quero percorrer toda a tabela e SIM SOMENTE o registro que está sendo incluido ou ALTERADO.

Suponha que voce já tem um funcionario cadastrado com os valores de salário até setembro. Daí voce altera e digita o valor de OUTUBRO, entao o campo TOTALSALARIOS será alterado e nele constará o valor até OUTUBRO, sacou? Do jeito que eu fiz é que está acontecendo de varrer toda a tabela e está demorando um pouco para processar, portanto, meu método está errado. Obrigado assim mesmo pela dica, claro que eu vou anotá-la, se precisar de varrer toda a tabela já tenho uma pronta! :wink:


GOSTEI 0
Paulo_amorim

Paulo_amorim

13/10/2008

Olá

Por que você não faz uma trigger para AFTER UPDATE, ao invés (ou além) do AFTER INSERT? O que você fez é para inserção, basta um para atualização, eu creio.

Espero que ajude.

Até+


GOSTEI 0
Klr2

Klr2

13/10/2008

Paulo_Amorim

Já tentei fazer isso, mas ocorre um erro de concorrencia se nao me engano. Além do mais, o que tá pegando é que ESSA QUE EU FIZ, ATUALIZA TODA A TABELA e eu PRECISO só de atualizar o REGISTRO CORRENTE sendo ALTERADO ou INSERIDO. Essa até que funciona, mas para tooooda a tabela...

Obrigado assim mesmo pela dica, tá anotada! :wink:


GOSTEI 0
Paulo_amorim

Paulo_amorim

13/10/2008

Olá

A trigger que você fez não faz pra tooooda a tabela não. Se vc coloca a cláusula where pelo código, isso deve ser único.

Quanto ao seu problema de concorrência, precisaria fazer testes. Mas de cara assim, talvez pudesse atuar no BEFORE UPDATE.

´Noves fora´ o uso de new ou old na soma, pode-se tentar:

CREATE TRIGGER soma
FOR tabela ACTIVE
BEFORE insert OR update
BEGIN
  new.totalsalario = new.mes1 + new.mes2 +...
END;


Espero que ajude

Até+


GOSTEI 0
Klr2

Klr2

13/10/2008

Exatamente Paulo_Amorim!

:oops: :oops: Eu esqueci desse detalhe na hora de escrever aqui. Só faz para o NOVO codigo sendo inserido mas nao atua quando eu tento dar o UPDATE e quando coloco ´OR UPDATE´ dao os erros de concorrencia que eu citei. Vou fazer uns testes pra ver se descubro a causa disso. Muito obrigado pela dica! Espero que esta funcione, pois estou já em situacao de perder os cabelos por causa da cabeça quente. :lol:

Valeu


GOSTEI 0
Joaoshi

Joaoshi

13/10/2008

Colega, tente assim:

ALTER TABLE SuaTabela ADD TOTAL COMPUTED BY (MES1 + MES2 + MES3 + MES4 + MES5 + MES6 + MES7 + MES8 + MES9 + MES10 + MES11 + MES12);


Espero ter ajudado.


GOSTEI 0
Klr2

Klr2

13/10/2008

JoaoShi.

Realmente!

Funcionou! Eu já tinha criado um campo desses na minha tabela e deu um pau danado. Mas não era o mesmo tipo de campo, agora, observando bem. O que eu fiz, foi seguir um exemplo que está na Revista Clube Delphi edição 99 página 51 matéria do Adriano Santos, onde ele falava sobre as novidades do Firebird 2.1 e cita campos calculados.
Lá ele cita o exemplo :

CREATE TABLE PRODUTOS(
PRODUTO VARCHAR(30),
QUANTIDADE INT,
PRECO DOUBLE PRECISION,
TOTAL GENERATED ALWAYS AS (QUANTIDADE * PRECO))

Bom, troca daqui e dali, eu criei minha tabela usando o GENERATED ALWAYS somando os meses que eu queria e pela teoria lá explicada, eu achei que iria dar super certo e não precisava me preocupar mais com isso. Agora vejo que há diferença, pelo menos na ATUAÇÂO do comando COMPUTED BY e GENERATED ALWAYS. Cheguei a conclusão de que preciso estudar mais sobre Firebird.

OBRIGADO!
Resolvi meu problema completamente!


GOSTEI 0
Klr2

Klr2

13/10/2008

Bom, na verdade, não funcionou!!!!!!

Para um registro só, funciona! Mas como tenho um grid e digito vários registros de uma vez, quando mando incluir via while not(tabela.eof) surge o pau...

[b]attempted update of read-only column. Error Code -151. (Traduzindo que é mais fácil... ) Esta coluna não pode ser regravada porque ela é derivada de uma função SQL ou expressão. A SQL UPDATE FUNCIONARIOS SET SAL9 =? ,TOTALSAL =? where CODFUNC =? and MES =?;

Carambolas... :cry:

Achei que tinha resolvido!!!!


GOSTEI 0
POSTAR