web-dev-qa-db-fra.com

Oracle - Abort dans un déclencheur "avant insert" sans lancer une exception

Je sais que c'est une chose affreuse à faire pour de nombreuses raisons, mais je suis en mode fait des choses et nous avons un logiciel que nous ne pouvons pas modifier, qui écrit des enregistrements à une table. Certains de ces archives, pour des raisons commerciales, nous ne voulons pas dans ce tableau. Je pensais que je pouvais écrire un déclencheur qui "abandonne" l'une de ces lignes sans lancer une erreur (afin que l'application ne soit pas échouée à l'avant, nous voulons que cela pensait que cela a fait sa chose). Je suis intimement familiarisé avec cette demande et je sais que cela ne provoquera pas d'effets secondaires laids, nous ne pouvons tout simplement pas la modifier pour se comporter de la manière dont nous en avons besoin.

Alors, est-ce possible, et sinon, quelle serait une autre façon d'y aller? Je pensais avoir une sorte de travail qui nettoie systématiquement la table pour des dossiers que nous ne voulons pas, mais je préférerais que ces dossiers ne soient jamais là pour commencer, il n'y a donc pas de degré de "saleté" à la fois dans le tableau.

3
Paolo Bergantino

Le seul moyen d'obtenir une gâchette sur une table pour empêcher une opération INSERT de la complétion est de lancer une erreur.

Comme vous l'avez dit, un piratage énorme, mais vous pouviez

  • Renommer la table
  • Créer une vue qui a le même nom que la table d'origine
  • Créé un instead of déclencheur sur cette vue qui ne fait qu'un INSERT sur la table si vous voulez que la ligne soit persistée. Sinon, le déclencheur ne ferait rien.

Cela devrait fonctionner tant que l'application ne fait pas de MERGE dans la table. Bien sûr, c'est un piratage sur un piratage afin que cela ne va certainement pas gagner de récompenses pour le code propre.

9
Justin Cave

Vous pouvez également utiliser base de données privée virtuelle pour masquer ces lignes des utilisateurs avant qu'ils ne soient nettoyés.

0
sjk

Le moyen le plus simple et le plus facile d'accomplir cela consiste à utiliser une table temporaire et un déclencheur de déclaration:

1) Faites une table temporaire avec la clé principale de vos enregistrements

create global temporary table TMP_ID_NUMBER
(
  id NUMBER(9) not null
)
on commit delete rows;

2) Trigger

Insérez tous les enregistrements que vous ne voulez pas entrer dans la table temporaire ...

create or replace trigger MY_TEST_REMOVE_IDS_TR
  before insert
  on MY_TEST 
  for each row
begin
  if :new.Id in (100, 101, 501) then
    insert into tmp_id_number
      (id)
    values
      (:new.Id);
  end if;
end MY_TEST_REMOVE_IDS_TR;

3) Déclencheur de déclaration

Et retirez-les de votre table de base dans le déclencheur après la déclaration ...

create or replace trigger MY_TEST_REMOVE_IDS_STAT_TR
  after insert
  on MY_TEST 
begin
  delete MY_TEST d
   where d.Id in (select t.Id
                  from Tmp_Id_Number t);
end MY_TEST_REMOVE_IDS_STAT_TR;
0