sql >> データベース >  >> RDS >> Oracle

oracle plsqlトリガーを使用して誕生日から年齢を計算し、年齢を表に挿入します

    助けてください...私は本当にこれが必要です...

    いいえ、しません。注意を払うかどうかはわかりません。そして、あなたがすべき理由はありません:-)しかし:

    データベースに年齢を保存しないでください。 あなたは時々間違っていることが絶対に保証されています。年齢は人によって毎年変わりますが、人によっては毎日変わります。つまり、毎日実行して年齢を更新するには、バッチジョブが必要です。これが失敗した場合、または非常に厳密ではない 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)として宣言することを真剣に検討したいと思います 「可能な」値のみが含まれるようにするため。



    1. mysqlルートパスワードを忘れた

    2. ClusterControl 1.5-自動バックアップ検証、バックアップとクラウド統合からスレーブを構築

    3. Postgresのstrftimeに相当

    4. Debian 5のphpMyAdminでMySQLを管理する(Lenny)