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

Oracleで列を読み取り専用にする最も簡単な方法は何ですか?

    INITIATIVEIDを参照するデータが入力された子テーブルがある場合 Oracleは、親の主キーを変更して孤立した行を作成できないようにすることで、主キーの値を自動的に変更できないようにする必要があります。したがって、たとえば、TPM_INITIATIVESへの外部キー制約を持つ子テーブルがある場合 この子テーブルには、INITIATIVEIDの行があります。 17の場合、INITIATIVEIDを変更することはできません。 TPM_INITIAITVESの行の 現在の値が17のテーブル。TPM_INITIATIVESの特定の行を参照する行が子テーブルにない場合 テーブルでは、値を変更できますが、おそらく、関係がない場合、主キーの値を変更することは、定義上、データの整合性の問題を引き起こす可能性がないため、重要ではありません。もちろん、TPM_INITIATIVESに新しい行を挿入するコードを作成することもできます。 新しいINITIATIVEIDを使用 、古い行を参照する子テーブルのすべての行を新しい行を参照するように変更してから、古い行を変更します。しかし、これは提案されたソリューションのいずれにもとらわれることはありません。

    アプリケーションで子テーブルが定義されているが、適切な外部キー制約が宣言されていない場合は、それが問題を解決するための最良の方法です。

    そうは言っても、ビューを作成するArnonのソリューションは機能するはずです。テーブルの名前を変更し、既存のテーブルと同じ名前のビューを作成し、(潜在的に)INITIATIVEIDを更新しないビューにINSTEADOFトリガーを定義します。 桁。アプリケーションの他のビットを変更する必要はありません。

    テーブルにトリガーを定義することもできます

    CREATE TRIGGER trigger_name 
      BEFORE UPDATE ON TPM_INITIATIVES  
      FOR EACH ROW
    DECLARE
    BEGIN
      IF( :new.initiativeID != :old.initiativeID )
      THEN
        RAISE_APPLICATION_ERROR( -20001, 'Sorry Charlie.  You can''t update the initiativeID column' );
      END IF;
    END;
    

    もちろん、誰かがトリガーを無効にして更新を発行する可能性があります。ただし、攻撃者を阻止しようとしているのではなく、バグのあるコードであると想定しています。

    ただし、表示されている症状の説明に基づいて、このテーブルの列への変更の履歴をログに記録して、穴を推測して塞ぐのではなく、実際に何が起こっているのかを判断できるようにする方が理にかなっているようです。 -一つ。したがって、たとえば、次のようなことができます

    CREATE TABLE TPM_INITIATIVES_HIST (
       INITIATIVEID    NUMBER NOT NULL,
       NAME            VARCHAR2(100) NOT NULL,
       ACTIVE          CHAR(1) NULL,
       SORTORDER       NUMBER NULL,
       SHORTNAME       VARCHAR2(100) NULL,
       PROJECTTYPEID   NUMBER NOT NULL,
       OPERATIONTYPE   VARCHAR2(1) NOT NULL,
       CHANGEUSERNAME  VARCHAR2(30),
       CHANGEDATE      DATE,
       COMMENT         VARCHAR2(4000)
    );
    
    CREATE TRIGGER trigger_name 
      BEFORE INSERT or UPDATE or DELETE ON TPM_INITIATIVES  
      FOR EACH ROW
    DECLARE
      l_comment VARCHAR2(4000);
    BEGIN
      IF( inserting )
      THEN
        INSERT INTO tpm_initiatives_hist( INITIATIVEID, NAME, ACTIVE, SORTORDER, SHORTNAME, PROJECTTYPEID, 
                                          OPERATIONTYPE, CHANGEUSERNAME, CHANGEDATE )
          VALUES( :new.initiativeID, :new.name, :new.active, :new.sortOrder, :new.shortName, :new.projectTypeID, 
                  'I', USER, SYSDATE );
      ELSIF( inserting )
      THEN
        IF( :new.initiativeID != :old.initiativeID )
        THEN
          l_comment := 'Initiative ID changed from ' || :old.initiativeID || ' to ' || :new.initiativeID;
        END IF;
        INSERT INTO tpm_initiatives_hist( INITIATIVEID, NAME, ACTIVE, SORTORDER, SHORTNAME, PROJECTTYPEID, 
                                          OPERATIONTYPE, CHANGEUSERNAME, CHANGEDATE, COMMENT )
          VALUES( :new.initiativeID, :new.name, :new.active, :new.sortOrder, :new.shortName, :new.projectTypeID, 
                  'U', USER, SYSDATE, l_comment );
      ELSIF( deleting )
      THEN
        INSERT INTO tpm_initiatives_hist( INITIATIVEID, NAME, ACTIVE, SORTORDER, SHORTNAME, PROJECTTYPEID, 
                                          OPERATIONTYPE, CHANGEUSERNAME, CHANGEDATE )
          VALUES( :old.initiativeID, :old.name, :old.active, :old.sortOrder, :old.shortName, :old.projectTypeID, 
                  'D', USER, SYSDATE );
      END IF;
    END;
    

    次に、TPM_INITIATIVES_HISTにクエリを実行できます。 時間の経過とともに特定の行に加えられたすべての変更を確認します。したがって、主キーの値が変更されているのか、誰かが非キーフィールドを変更しているだけなのかを確認できます。理想的には、変更の追跡に役立つように履歴テーブルに追加できる追加の列がある場合があります(つまり、V$SESSIONから何かがある可能性があります 役に立つかもしれません。



    1. cx_oracleを使用してMERGEから影響を受ける行の数を返します

    2. ORA-01652:表領域で一時セグメントを128だけ拡張できません。システム:拡張方法は?

    3. Alembicはカラムの変更を自動生成できますか?

    4. md5ハッシュをmysqlに効率的に保存するためのベストプラクティス