1
votes

Comment empêcher le déclencheur de mettre à jour l'horodatage d'une colonne dans Oracle?

J'ai une table qui a une colonne sur laquelle j'ai défini un déclencheur pour mettre à jour l'horodatage lorsqu'il y a une mise à jour sur la ligne

MERGE INTO mytable
USING dual
ON (id = ?)
WHEN MATCHED THEN
    UPDATE SET
        stext = case when sid = ? then ? else stext end,
        ttext = case when tid = ? then ? else ttext end

Cependant, lorsque certains SQL sont exécutés sur la table, je ne veux PAS que la colonne «last_updated» soit mise à jour. Par exemple, lorsque le SQL ci-dessous met à jour cette table, je ne veux PAS que le déclencheur se déclenche. J'ai besoin que la colonne conserve la valeur last_updated afin que mes autres requêtes ne soient pas gâchées. Cependant, lorsque d'autres SQL mettent à jour les données, je souhaite que la colonne soit mise à jour.

Des idées sur la façon dont cela pourrait être fait?

CREATE TABLE mytable (
    id NUMBER NOT NULL,
    sid VARCHAR(10) NOT NULL,
    stext VARCHAR(10),
    tid VARCHAR(10),
    ttext VARCHAR(10),
    last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT unique PRIMARY KEY (id) ENABLE
);

CREATE OR REPLACE trigger last_updated_trigger
  BEFORE UPDATE ON mytable
  FOR EACH ROW
BEGIN
    select systimestamp into :new.last_updated from dual;
END;
/


3 commentaires

Soit vous voulez que la valeur soit définie dans un déclencheur, soit vous ne le faites pas. Vous devriez peut-être simplement définir la valeur manuellement et supprimer le déclencheur.


Merci Gordon. Existe-t-il un moyen de modifier le déclencheur afin qu'il ne mette à jour la colonne que si une valeur n'est pas fournie par le SQL et / ou modifie le SQL pour conserver l'ancienne valeur de la colonne?


Mettre mon chapeau d'auditeur informatique. Vous venez d'échouer l'audit. Vous avez une colonne qui indique quand une action a eu lieu sur une ligne, mais parfois id ne l'indique pas du tout. Alors, que signifie réellement la colonne "last_updated".


3 Réponses :


0
votes

Vous pouvez facilement conserver une valeur fournie et n'insérer l'heure actuelle que si elle n'est pas fournie:

CREATE OR REPLACE trigger last_updated_trigger
  BEFORE UPDATE ON mytable
  FOR EACH ROW
BEGIN
    :new.last_updated := coalesce(:new.last_updated, systimestamp);
END;


6 commentaires

Merci, @Barbaros. Je vais l'essayer. Aussi, une idée comment modifier le sql de fusion publié dans ma question pour conserver l'horodatage last_updated?


Salut @Barbaros, j'ai essayé le déclencheur ci-dessus, mais maintenant il ne met pas à jour la colonne last_updated même si une valeur n'est pas fournie par le sql?


Salut cher @Jared, je n'ai pas répondu, j'ai juste édité le style existant :) pour plus de simplicité ...


Salut @ BarbarosÖzhan, FYI, le déclencheur ci-dessus ne fonctionne pas pour moi. La nouvelle définition de déclencheur a complètement arrêté la mise à jour du champ «last_updated».


@Jared. . . Ce déclencheur doit être mis à jour last_updated , avec une certaine valeur.


eh bien, j'ai ajouté une réponse que vous pouvez vérifier @Jared



0
votes

Si vous ne souhaitez pas déclencher le déclencheur lorsque vous mettez à jour les colonnes STEXT ou TTEXT, essayez ceci:

CREATE OR REPLACE trigger last_updated_trigger
  BEFORE UPDATE ON mytable
  FOR EACH ROW
BEGIN
    if (not updating('stext') and not updating('ttext')) then
       :new.last_updated := systimestamp;
    end if;
END;

Merci


1 commentaires

Merci @gogocho. Mais il existe d'autres SQL qui mettent à jour le stext et le ttext qui doivent mettre à jour 'last_updated'



0
votes

Vous pouvez placer cette instruction SQL spécifique dans une PROCÉDURE dans laquelle les informations du module sont mises à jour pour l'application concernée ( appelez toujours cette instruction à partir de cette procédure uniquement ) telle que

CREATE OR REPLACE trigger last_updated_trigger
  BEFORE UPDATE ON mytable
  FOR EACH ROW
  v_module  VARCHAR2(80);
  v_action  VARCHAR2(80);  
BEGIN
  DBMS_APPLICATION_INFO.READ_MODULE(v_module, v_action);
 IF v_module != 'MERGE_TEXT' THEN
  :new.last_updated  := systimestamp;
 END IF;
END;
/

puis distinguer ce module appelant dans le déclencheur tel que

CREATE OR REPLACE PROCEDURE Merge_Text AS
BEGIN
  DBMS_APPLICATION_INFO.SET_MODULE($$plsql_unit,null);
  MERGE INTO mytable
  USING dual
      ON (id = ?)
  WHEN MATCHED THEN
    UPDATE SET
        stext = case when sid = ? then ? else stext end,
        ttext = case when tid = ? then ? else ttext end;
END;
/


1 commentaires

Merci @Barbaros. Cependant, j'ai opté pour un PreparedStatement car PreparedStatements peut être groupé du côté client, mais CallableStatements ne peut pas être groupé. J'aurai besoin d'utiliser Collections, Records et je n'ai trouvé aucun code JDBC décent en ligne qui effectue des opérations en bloc, afin que je puisse utiliser CallableStatements!