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

トリガーを通過する文字が変化するコンマを使用してデータを保存するにはどうすればよいですか?

    format()を使用できます 識別子とリテラルを自動的に正しく処理するため、動的SQLクエリの作成がはるかに簡単になります。人々が通常見落としていることの1つは、(...).*を使用して、単一のレコード式をそのすべての列に展開できることです。 -これはNEWでも機能します およびOLD トリガーに変数を記録します。例: select (new).*

    using executeのキーワード 声明。レコードとテキスト表現の間でレコードを相互に変換する必要はありません。

    その可能性を使用して、トリガー関数を次のように簡略化できます。

    DECLARE 
      l_sql text;
    BEGIN
        IF TG_TABLE_SCHEMA = 'public' THEN
          newtable := TG_TABLE_NAME || '_actividad';
        ELSE
          newtable := TG_TABLE_SCHEMA || '_' || TG_TABLE_NAME || '_actividad';
        END IF;
    
        PERFORM creartablaactividad(TG_TABLE_SCHEMA, TG_TABLE_NAME);
        l_sql := 'INSERT INTO actividad.%I  SELECT current_user, current_timestamp, %L, ($1).*';
    
        IF TG_OP = 'DELETE' THEN
          execute format(l_sql, newtable, 'D') using OLD;
          RETURN OLD;
        ELSE
          -- covers UPDATE and INSERT
          execute format(l_sql, newtable, 'U') using NEW;
          RETURN NEW;
        END IF;
    
        RETURN NULL; -- result is ignored since this is an AFTER trigger
    END;
    

    %Iのようなプレースホルダーを使用する および%L また、実際のSQLを一度だけ定義して再利用することもできます。これらの「パラメータ」は、format()に置き換えられます。 関数($1を保持します )

    ($1).*の使用に注意してください SQL文字列内。これにより、executeが作成されます ステートメントは、レコードパラメータ$1を展開します そのすべての列に。レコード自体は、USINGで「ネイティブに」渡されます キーワード。

    INSERTの使用 ターゲット列リストなし(insert into some_table ... insert into some_table (col1, col2, ...) ... )はかなり壊れやすいことです。ソースとターゲットが一致しない場合、挿入は非常に簡単に失敗する可能性があります。 。

    監査テーブルで大規模なレポートを実行しない場合(明示的な列名を使用する方がはるかに効率的です)、JSONを使用したより一般的な監査トリガーを検討することをお勧めします。 またはHSTORE レコード全体を格納する列。利用可能な既製の監査トリガーがいくつかあります:




    1. SQL Server-特定の条件を満たす列を選択しますか?

    2. SQLDeveloperでデータをインポートするときにタイムスタンプを読み取る

    3. MySQLストアドプロシージャを呼び出すときにパケットの順序が正しくないエラー

    4. 直前にclient_min_messagesを警告に設定したにもかかわらずINFO出力