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.