sql >> Databáze >  >> RDS >> Oracle

Jaký je nejjednodušší způsob, jak vytvořit sloupec POUZE PRO ČTENÍ v Oracle?

Pokud jsou podřízené tabulky naplněny daty, které odkazují na INITIATIVEID Oracle by měl automaticky ztížit změnu hodnoty primárního klíče tím, že vám zabrání ve vytváření osiřelých řádků změnou primárního klíče rodiče. Pokud tedy například existuje podřízená tabulka, která má omezení cizího klíče na TPM_INITIATIVES a v této podřízené tabulce je řádek s INITIATIVEID ze 17, nebudete moci změnit INITIATIVEID řádku v TPM_INITIAITVES tabulka, jejíž aktuální hodnota je 17. Pokud v žádné podřízené tabulce není žádný řádek, který odkazuje na konkrétní řádek v TPM_INITIATIVES v tabulce, můžete změnit hodnotu, ale pravděpodobně, pokud neexistují žádné vztahy, je změna hodnoty primárního klíče nedůležitá, protože podle definice nemůže způsobit problém s integritou dat. Samozřejmě můžete mít kód, který vloží nový řádek do TPM_INITIATIVES s novým INITIATIVEID , změňte všechny řádky v podřízené tabulce, které odkazují na starý řádek, aby odkazovaly na nový řádek, a poté upravte starý řádek. To však nebude chyceno žádným z navrhovaných řešení.

Pokud vaše aplikace definovala podřízené tabulky, ale nedeklarovala příslušná omezení cizího klíče, byl by to nejlepší způsob, jak problém vyřešit.

Jak již bylo řečeno, Arnonovo řešení vytvoření pohledu by mělo fungovat. Přejmenovali byste tabulku, vytvořili pohled se stejným názvem jako stávající tabulka a (potenciálně) definovali MÍSTO spouštěče v pohledu, který by jednoduše nikdy neaktualizoval INITIATIVEID sloupec. To by nemělo vyžadovat změny jiných částí aplikace.

Můžete také definovat spouštěč na stole

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;

Někdo by samozřejmě mohl spoušť deaktivovat a vydat aktualizaci. Ale předpokládám, že se nesnažíte zastavit útočníka, jen zabugovaný kus kódu.

Na základě popisu příznaků, které vidíte, by se však zdálo smysluplnější zaznamenat historii změn sloupců v této tabulce, abyste mohli skutečně určit, co se děje, než hádat a snažit se zacpat díry. -po jednom. Takže byste mohli udělat například něco takového

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;

Poté můžete zadat dotaz na TPM_INITIATIVES_HIST zobrazit všechny změny, které byly v průběhu času provedeny na konkrétním řádku. Můžete tedy vidět, zda se mění hodnoty primárního klíče nebo zda někdo pouze mění neklíčová pole. V ideálním případě můžete mít další sloupce, které můžete přidat do tabulky historie, abyste pomohli sledovat změny (tj. možná existuje něco z V$SESSION to by mohlo být užitečné).



  1. Výjimky Python MySQLdb

  2. Laravel:vztah jeden k jednomu se stane vztahem jednoho k mnoha

  3. Správný způsob, jak přidat neuvedený text z pole do regulárního výrazu v postgresu?

  4. sql pro výpočet bodů za hry