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

Count(*)が正しく機能しない

    いくつかのポイント。まず、自律トランザクションプラグマを誤用しています。これは、メイントランザクションとは独立してコミットまたはロールバックする必要がある個別のトランザクションを対象としています。これを使用してメイントランザクションをロールバックしています。エラーがない場合はコミットしません。

    そして、誰かが言及したそれらの「予期しない結果」?そのうちの1つは、カウントが常に0を返すことです。したがって、プラグマは誤用されているため削除し、カウントが適切な値を返すようにします。

    もう1つは、トリガー内にコミットまたはロールバックがないことです。エラーを発生させ、制御コードに必要な処理を実行させます。ロールバックはプラグマによるものだと私は知っています。プラグマを削除するときは、それらを削除することを忘れないでください。

    次のトリガーが機能します:

    CREATE OR REPLACE TRIGGER trg_mytable_biu 
    BEFORE INSERT OR UPDATE ON mytable 
    FOR EACH ROW 
    WHEN (NEW.TYPEB = 'Bert') -- Don't even execute unless this is Bert
    DECLARE
        L_COUNT NUMBER;
    BEGIN
        SELECT  COUNT(*) INTO L_COUNT
        FROM    MYTABLE 
        WHERE   ARTICLE = :NEW.ARTICLE
            AND TYPEB = :NEW.TYPEB;
    
        IF L_COUNT > 0  THEN
            RAISE_APPLICATION_ERROR( -20001, 'Bert already exists!' );
        ELSIF :NEW.STOCK_COUNT > 1 THEN
            RAISE_APPLICATION_ERROR( -20001, 'Can''t insert more than one Bert!' );
        END IF;
    END;
    

    ただし、テーブルのトリガーがそのテーブルに個別にアクセスすることはお勧めできません。通常、システムはそれを許可しません。このトリガーは、「後」に変更された場合、まったく実行されません。実行が許可されている場合、すでにわかっているように、得られた結果を確認することはできません。実際、上記のトリガーが機能することに少し驚いています。実際のデータベースで使用するのは不安です。

    トリガーが必要である場合の最良のオプション ターゲットテーブルへのアクセスは、ビューの背後にあるテーブルを非表示にし、ビューに「代わりの」トリガーを書き込むことです。 それ トリガーは必要なすべてのテーブルにアクセスできます。



    1. SQL再帰CTE:プロパティによってリンクされたオブジェクトの検索

    2. Oracleのグローバル非パーティションインデックス

    3. PostgreSQL-このクエリ/インデックスを改善する方法

    4. テーブルをあるスキーマから別のスキーマに移動しますか?