请帮助...我真的需要这个......
不,你不知道。我不确定你会注意,并没有理由你应该:-)但:
不要在您的数据库中存储年龄。你绝对保证偶尔会出错。每个人每年的年龄都会发生变化,但是,一些人每天都会变化。这反过来意味着您需要每天运行批处理作业并更新年龄。如果这失败了,或者不是极其严格的并且运行两次,那么您就遇到了麻烦。
你应该总是计算你需要它的年龄。这是一个相当简单的查询,并且在较长时间内为您节省很多痛苦。
select floor(months_between(sysdate,<dob>)/12) from dual
我已经成立了一个小SQL Fiddle证明
现在,真正回答你的问题
这个程序工作正常,但只有一个行,,,但为所有行 我需要触发,但如果我从触发器调用它,然后发生错误 ...
你没有提到的错误,请在将来做到这一点,因为它是非常有帮助的,但我怀疑你要
ORA-04091:表string.string都在变异,触发/功能可能不是 看到它
这是因为您的过程正在查询正在更新的表。 Oracle不允许这样做以保持数据的读一致性视图。避免这种情况的方法是不查询您不需要执行的表。再次
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;
请注意,我使用的months_between()
功能,因为不是所有年有365天:改变你的方法来返回给定的出生日期正确结果的函数。
在触发器中,您直接将值赋给列。
CREATE OR REPLACE TRIGGER agec before INSERT OR UPDATE ON dates
FOR EACH ROW
BEGIN
:new.age := get_age(:new.dob);
END;
:new.<column>
的语法是将<column>
正在更新的参考。在这种情况下,:new.age
是要放入表中的实际值。
这意味着您的表格将自动更新,即the point of a DML trigger。
正如你所看到的,根本没有什么功能;你的触发器可以成为
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;
不过,话说回来,如果你要在数据库中的其他地方使用该功能,然后把它分开。将多个地方使用的代码保存在这样的函数中是一个很好的习惯,所以它总是以相同的方式使用。它还可以确保每当有人计算年龄时,他们都会正确做到。
作为一点一点,你确定你想让人们成为9,999岁?或者0.000000000001998 (proof)? Numeric precision是基于显着数字的数字;这个(根据Oracle)是非零数字只。你可以很容易被这件事发现。数据库的要点是将可能的输入值限制为仅限于有效的输入值。我会认真考虑宣布你的年龄栏为number(3,0)
,以确保只包含“可能的”值。
根据需要继续计算它会更好吗?如果你直接插入蝙蝠的年龄,你将不得不一直更新它,否则你将会以错误的年龄结束。 – Fluffeh