Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Tính tuổi từ ngày sinh với trình kích hoạt oracle plsql và chèn tuổi vào bảng

xin hãy giúp đỡ ... tôi thực sự cần cái này ...

Không, bạn không. Tôi không chắc bạn sẽ chú ý; và không có lý do gì bạn nên :-) nhưng:

Không lưu trữ tuổi trong cơ sở dữ liệu của bạn. Bạn hoàn toàn được đảm bảo rằng thỉnh thoảng sẽ sai. Tuổi tác thay đổi hàng năm đối với mỗi người, tuy nhiên, nó thay đổi hàng ngày đối với một số người. Điều này có nghĩa là bạn cần một công việc hàng loạt để chạy mỗi ngày và cập nhật độ tuổi. Nếu điều này không thành công hoặc không cực kỳ nghiêm ngặt và bị chạy hai lần, bạn đang gặp rắc rối.

Bạn nên luôn luôn tính tuổi khi bạn cần. Đây là một truy vấn khá đơn giản và giúp bạn tiết kiệm rất nhiều công sức về lâu dài.

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

Tôi đã thiết lập một SQL Fiddle nhỏ để chứng minh

Bây giờ, để thực sự trả lời câu hỏi của bạn

thủ tục này hoạt động tốt nhưng chỉ cho một hàng, nhưng đối với tất cả các hàng, tôi cần trình kích hoạt nhưng nếu tôi gọi nó từ một trình kích hoạt thì lỗi ...

Bạn không đề cập đến lỗi, vui lòng làm điều này trong tương lai vì nó rất hữu ích, nhưng tôi nghi ngờ bạn đang mắc phải

ORA-04091:table string.string đang thay đổi, trigger / function có thể không nhìn thấy nó

Điều này là do thủ tục của bạn đang truy vấn bảng đang được cập nhật. Oracle không cho phép điều này để duy trì chế độ xem dữ liệu nhất quán có thể đọc được. Cách để tránh điều này là không truy vấn bảng, điều bạn không cần thực hiện. Thay đổi thủ tục của bạn thành một hàm trả về kết quả đúng với ngày sinh:

Số trả về
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;

Lưu ý một lần nữa rằng tôi đang sử dụng months_between() hoạt động như không phải tất cả các năm đều có 365 ngày.

Trong trình kích hoạt của mình, bạn chỉ định giá trị trực tiếp cho cột.

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

:new.<column> cú pháp là một tham chiếu đến <column> đang được cập nhật. Trong trường hợp này :new.age là giá trị thực tế sẽ được đưa vào bảng.

Điều này có nghĩa là bảng của bạn sẽ tự động được cập nhật, đây là điểm của trình kích hoạt DML.

Như bạn có thể thấy, có rất ít điểm liên quan đến chức năng; trình kích hoạt của bạn có thể trở thành

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; 

Tuy nhiên, đã nói rằng, nếu bạn định sử dụng chức năng này ở nơi khác trong cơ sở dữ liệu thì hãy giữ nó riêng biệt. Thực tiễn tốt là giữ mã được sử dụng ở nhiều nơi trong một hàm như thế này để nó luôn được sử dụng theo cùng một cách. Nó cũng đảm bảo rằng bất cứ khi nào bất kỳ ai tính toán tuổi, họ sẽ thực hiện đúng.

Ngoài ra, bạn có chắc chắn muốn cho phép mọi người 9,999 tuổi không? Hoặc 0,000000000001998 (bằng chứng)? Độ chính xác của số dựa trên số lượng đáng kể các chữ số; cái này (theo Oracle) là khác không chỉ số. Bạn có thể dễ dàng bị phát hiện bởi điều này. Mục đích của cơ sở dữ liệu là hạn chế các giá trị đầu vào có thể có chỉ những giá trị hợp lệ. Tôi thực sự cân nhắc việc khai báo cột tuổi của bạn là number(3,0) để đảm bảo rằng chỉ các giá trị "có thể" mới được đưa vào.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm thế nào để gọi hàm Oracle hoặc thủ tục được lưu trữ bằng cách sử dụng khuôn khổ bền vững mùa xuân?

  2. Tại sao mẫu ngủ đông này số lượng lớn

  3. Cách giải quyết ORA-02014:không thể chọn CẬP NHẬT từ chế độ xem với DISTINCT, GROUP BY

  4. Đảo ngược một chuỗi trong SQL và PL / SQL Một ví dụ

  5. TO_CHAR của một loại Oracle PL / SQL TABLE