Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Calculando a idade do aniversário com o gatilho oracle plsql e insira a idade na tabela


por favor me ajudem... preciso muito disso...

Não, você não. Não tenho certeza se você prestará atenção; e não há razão para você :-) mas:

Não armazene a idade em seu banco de dados. Você está absolutamente garantido de estar errado ocasionalmente. A idade muda a cada ano para cada pessoa, no entanto, muda todos os dias para algumas pessoas. Isso, por sua vez, significa que você precisa de um trabalho em lote para ser executado todos os dias e atualizar a idade. Se isso falhar ou não for extremamente rigoroso e é executado duas vezes, você está em apuros.

Você deve sempre calcular a idade quando você precisar dele. É uma consulta bastante simples e poupa muita dor a longo prazo.
select floor(months_between(sysdate,<dob>)/12) from dual

Eu configurei um pouco SQL Fiddle para demonstrar

Agora, para realmente responder sua pergunta

este procedimento funciona bem, mas para apenas uma linha,,, mas para todas as linhas, eu preciso do gatilho, mas se eu chamá-lo de um gatilho, o erro ocorre ...

Você não menciona o erro. Faça isso no futuro, pois é muito útil, mas suspeito que você esteja recebendo

ORA-04091:a tabela string.string está mudando, o gatilho/função pode não ver

Isso ocorre porque seu procedimento está consultando a tabela que está sendo atualizada. A Oracle não permite isso para manter uma visualização consistente de leitura dos dados. A maneira de evitar isso é não consultar a tabela, o que você não precisa fazer. Altere seu procedimento para uma função que retorne o resultado correto dada a data de nascimento:
function get_age (pDOB date) return number is
   /* Return the the number of full years between 
      the date given and sysdate.
      */    
begin    
   return floor(months_between(sysdate,pDOB)/12);    
end;

Observe mais uma vez que estou usando o months_between() funcionar como nem todos os anos têm 365 dias.

Em seu gatilho, você atribui o valor diretamente à coluna.
CREATE OR REPLACE TRIGGER agec before INSERT OR UPDATE ON dates
FOR EACH ROW
BEGIN
   :new.age := get_age(:new.dob);
END;

O :new.<column> sintaxe é uma referência ao <column> que está sendo atualizado. Neste caso :new.age é o valor real que será colocado na tabela.

Isso significa que sua tabela será atualizada automaticamente, que é o ponto de um gatilho DML.

Como você pode ver, há pouco sentido para a função; seu gatilho pode se tornar
CREATE OR REPLACE TRIGGER agec before INSERT OR UPDATE ON dates
FOR EACH ROW
BEGIN
   :new.age := floor(months_between(sysdate,:new,DOB)/12);
END; 

No entanto, tendo dito isso, se você for usar essa função em outro lugar no banco de dados, mantenha-a separada. É uma boa prática manter o código usado em vários lugares em uma função como essa, para que seja sempre usado da mesma maneira. Também garante que, sempre que alguém calcular a idade, o fará corretamente.

Como um pouco de lado, você tem certeza de que deseja permitir que as pessoas tenham 9.999 anos de idade? Ou 0,000000000001998 (prova)? A precisão numérica é baseada no número de significativos dígitos; isso (de acordo com a Oracle) é diferente de zero Apenas números. Você pode facilmente ser pego por isso. O objetivo de um banco de dados é restringir os valores de entrada possíveis apenas àqueles que são válidos. Eu consideraria seriamente declarar sua coluna de idade como number(3,0) para garantir que apenas os valores "possíveis" sejam incluídos.