Wenn es untergeordnete Tabellen gibt, die mit Daten gefüllt sind, die auf INITIATIVEID
verweisen -Spalte sollte Oracle es automatisch erschweren, den Primärschlüsselwert zu ändern, indem verhindert wird, dass Sie verwaiste Zeilen erstellen, indem Sie den Primärschlüssel des übergeordneten Elements ändern. Wenn also beispielsweise eine untergeordnete Tabelle eine Fremdschlüsseleinschränkung für TPM_INITIATIVES
hat und es gibt eine Zeile in dieser untergeordneten Tabelle mit einer INITIATIVEID
von 17 können Sie die INITIATIVEID
nicht ändern der Zeile in TPM_INITIAITVES
Tabelle, deren aktueller Wert 17 ist. Wenn es keine Zeile in einer untergeordneten Tabelle gibt, die auf die bestimmte Zeile in TPM_INITIATIVES
verweist Tabelle, Sie könnten den Wert ändern, aber wenn es keine Beziehungen gibt, ist es vermutlich unwichtig, den Primärschlüsselwert zu ändern, da es per Definition kein Datenintegritätsproblem verursachen kann. Natürlich könnten Sie Code haben, der eine neue Zeile in TPM_INITIATIVES
einfügt mit einer neuen INITIATIVEID
, ändern Sie alle Zeilen in der untergeordneten Tabelle, die auf die alte Zeile verweisen, um auf die neue Zeile zu verweisen, und ändern Sie dann die alte Zeile. Dies wird jedoch von keiner der vorgeschlagenen Lösungen abgefangen.
Wenn Ihre Anwendung untergeordnete Tabellen definiert, aber nicht die entsprechenden Fremdschlüsseleinschränkungen deklariert hat, wäre dies der beste Weg, um das Problem zu lösen.
Davon abgesehen sollte Arnons Lösung zum Erstellen einer Ansicht funktionieren. Sie würden die Tabelle umbenennen, eine Ansicht mit demselben Namen wie die vorhandene Tabelle erstellen und (möglicherweise) einen INSTEAD OF-Trigger für die Ansicht definieren, der die INITIATIVEID
einfach nie aktualisieren würde Säule. Das sollte keine Änderungen an anderen Teilen der Anwendung erfordern.
Sie könnten auch einen Trigger für die Tabelle definieren
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;
Jemand könnte natürlich den Trigger deaktivieren und ein Update herausgeben. Aber ich gehe davon aus, dass Sie nicht versuchen, einen Angreifer aufzuhalten, sondern nur ein fehlerhaftes Stück Code.
Basierend auf der Beschreibung der Symptome, die Sie sehen, scheint es jedoch sinnvoller zu sein, den Verlauf der Änderungen an Spalten in dieser Tabelle zu protokollieren, damit Sie tatsächlich feststellen können, was vor sich geht, anstatt zu raten und zu versuchen, Löcher zu stopfen -einzeln. Sie könnten also zum Beispiel so etwas tun
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;
Dann können Sie TPM_INITIATIVES_HIST
abfragen um alle Änderungen anzuzeigen, die im Laufe der Zeit an einer bestimmten Zeile vorgenommen wurden. So können Sie sehen, ob sich die Primärschlüsselwerte ändern oder ob jemand nur die Nicht-Schlüsselfelder ändert. Idealerweise haben Sie zusätzliche Spalten, die Sie der Verlaufstabelle hinzufügen können, um die Verfolgung der Änderungen zu erleichtern (d. h. vielleicht gibt es etwas von V$SESSION
das könnte nützlich sein).