助けてください...私は本当にこれが必要です...
いいえ、しません。注意を払うかどうかはわかりません。そして、あなたがすべき理由はありません:-)しかし:
データベースに年齢を保存しないでください。 あなたは時々間違っていることが絶対に保証されています。年齢は人によって毎年変わりますが、人によっては毎日変わります。つまり、毎日実行して年齢を更新するには、バッチジョブが必要です。これが失敗した場合、または非常に厳密ではない 2回実行されると、問題が発生します。
常に 必要なときに年齢を計算します。これは非常に単純なクエリであり、長期的には多くの苦痛を軽減します。
select floor(months_between(sysdate,<dob>)/12) from dual
デモンストレーション用に小さなSQLフィドルを設定しました
さて、実際にあなたの質問に答えるために
この手順は正常に機能しますが、1行のみですが、すべての行に対してトリガーが必要ですが、トリガーから呼び出すとエラーが発生します...
エラーについては言及していません。非常に役立つので、今後これを行ってください。ただし、発生していると思われます。
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
テーブルに配置される実際の値です。
これは、テーブルが自動的に更新されることを意味します。これがDMLトリガーのポイントです。
ご覧のとおり、この関数にはほとんど意味がありません。トリガーは
になる可能性があります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(証明)?数値の精度は、重要なの数に基づいています。 数字;これ(Oracleによる)はゼロ以外 数字のみ。これで簡単に捕まえられます。データベースのポイントは、可能な入力値を有効な値のみに制限することです。あなたの年齢列をnumber(3,0)
として宣言することを真剣に検討したいと思います 「可能な」値のみが含まれるようにするため。