Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Obliczanie wieku od urodzin za pomocą wyzwalacza Oracle plsql i wstawianie wieku do tabeli

proszę o pomoc... naprawdę tego potrzebuję...

Nie, nie masz. Nie jestem pewien, czy zwrócisz uwagę; i nie ma powodu, dla którego miałbyś :-) ale:

Nie przechowuj wieku w swojej bazie danych. Masz absolutną gwarancję, że od czasu do czasu się pomylisz. Wiek zmienia się co roku dla każdej osoby, jednak dla niektórych zmienia się każdego dnia. To z kolei oznacza, że ​​potrzebujesz zadania wsadowego do codziennego uruchamiania i aktualizowania wieku. Jeśli to się nie powiedzie lub nie jest bardzo surowe i zostanie uruchomiony dwa razy, masz kłopoty.

Powinieneś zawsze obliczyć wiek, kiedy tego potrzebujesz. To dość proste zapytanie i na dłuższą metę oszczędza wiele bólu.

select floor(months_between(sysdate,<dob>)/12) from dual

Przygotowałem małe skrzypce SQL, aby zademonstrować

Teraz, aby odpowiedzieć na twoje pytanie

ta procedura działa dobrze, ale tylko dla jednego wiersza, ale dla wszystkich rowsi potrzebuję wyzwalacza, ale jeśli wywołam go z wyzwalacza, wystąpi błąd...

Nie wspominasz o błędzie, zrób to w przyszłości, ponieważ jest to bardzo pomocne, ale podejrzewam, że otrzymujesz

ORA-04091:tabela string.string mutuje, wyzwalacz/funkcja może go nie widzieć

Dzieje się tak, ponieważ twoja procedura wysyła zapytanie do aktualizowanej tabeli. Oracle nie zezwala na to, aby zachować spójność odczytu danych. Sposobem na uniknięcie tego jest unikanie zapytań do tabeli, czego nie musisz robić. Zmień procedurę na funkcję, która zwraca poprawny wynik podaną datą urodzenia:

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;

Zauważ jeszcze raz, że używam months_between() działają, ponieważ nie wszystkie lata mają 365 dni.

W wyzwalaczu następnie przypisz wartość bezpośrednio do kolumny.

CREATE OR REPLACE TRIGGER agec before INSERT OR UPDATE ON dates
FOR EACH ROW
BEGIN
   :new.age := get_age(:new.dob);
END;

:nowy. składnia jest odwołaniem do który jest aktualizowany. W tym przypadku :new.age to rzeczywista wartość, która zostanie umieszczona w tabeli.

Oznacza to, że Twoja tabela zostanie automatycznie zaktualizowana, co jest punktem wyzwalacza DML.

Jak widać, ta funkcja w ogóle nie ma sensu; Twój wyzwalacz może stać się

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; 

Jednak powiedziawszy to, jeśli zamierzasz używać tej funkcji w innym miejscu bazy danych, zachowaj ją oddzielnie. Dobrą praktyką jest przechowywanie kodu, który jest używany w wielu miejscach w takiej funkcji, aby zawsze był używany w ten sam sposób. Zapewnia również, że za każdym razem, gdy ktoś obliczy wiek, zrobi to poprawnie.

Na marginesie, czy na pewno chcesz, aby ludzie mieli 9999 lat? Lub 0.000000000001998 (dowód)? Dokładność liczbowa jest oparta na liczbie znaczących cyfry; to (według Oracle) jest niezerowe tylko liczby. Możesz łatwo zostać przez to złapany. Celem bazy danych jest ograniczenie możliwych wartości wejściowych tylko do tych, które są prawidłowe. Poważnie rozważyłbym zadeklarowanie kolumny wieku jako number(3,0) aby upewnić się, że uwzględniane są tylko „możliwe” wartości.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak dodać wskaźnik AD/BC do daty w Oracle?

  2. Wpływ EM SQL Monitor

  3. Mechanizm stosowany przez Oracle podczas wykonywania kopii zapasowych na gorąco

  4. Należy zadeklarować identyfikator PLS-00201 'PACKAGENAME.PROCEDURENAME'

  5. Programista SQL nie chce się uruchomić