Se houver tabelas filhas preenchidas com dados que fazem referência ao
INITIATIVEID
coluna, o Oracle deve dificultar automaticamente a alteração do valor da chave primária, impedindo que você crie linhas órfãs alterando a chave primária do pai. Assim, por exemplo, se houver uma tabela filha que tenha uma restrição de chave estrangeira para TPM_INITIATIVES
e há uma linha nesta tabela filha com um INITIATIVEID
de 17, você não poderá alterar o INITIATIVEID
da linha no TPM_INITIAITVES
tabela cujo valor atual é 17. Se não houver linha em nenhuma tabela filha que se refira à linha específica no TPM_INITIATIVES
table, você pode alterar o valor, mas, presumivelmente, se não houver relacionamentos, alterar o valor da chave primária não é importante, pois não pode, por definição, causar um problema de integridade de dados. Claro, você pode ter um código que insere uma nova linha em TPM_INITIATIVES
com um novo INITIATIVEID
, altere todas as linhas na tabela filha que se referem à linha antiga para se referir à nova linha e modifique a linha antiga. Mas isso não será aprisionado por nenhuma das soluções propostas. Se seu aplicativo definiu tabelas filhas, mas não declarou as restrições de chave estrangeira apropriadas, essa seria a melhor maneira de resolver o problema.
Dito isto, a solução de Arnon de criar uma visão deve funcionar. Você renomearia a tabela, criaria uma visualização com o mesmo nome da tabela existente e (potencialmente) definiria um gatilho INSTEAD OF na visualização que simplesmente nunca atualizaria o
INITIATIVEID
coluna. Isso não deve exigir alterações em outros bits do aplicativo. Você também pode definir um gatilho na tabela
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;
Alguém poderia, é claro, desabilitar o gatilho e emitir uma atualização. Mas estou assumindo que você não está tentando parar um invasor, apenas um pedaço de código com erros.
Com base na descrição de quais sintomas você está vendo, no entanto, parece fazer mais sentido registrar o histórico de alterações nas colunas desta tabela para que você possa realmente determinar o que está acontecendo, em vez de adivinhar e tentar tapar os buracos um -por um. Então, por exemplo, você poderia fazer algo assim
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;
Então você pode consultar
TPM_INITIATIVES_HIST
para ver todas as alterações que foram feitas em uma linha específica ao longo do tempo. Assim, você pode ver se os valores da chave primária estão mudando ou se alguém está apenas alterando os campos não-chave. Idealmente, você pode ter colunas adicionais que você pode adicionar à tabela de histórico para ajudar a rastrear as alterações (ou seja, talvez haja algo de V$SESSION
que pode ser útil).