IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Procédural MySQL Discussion :

Trigger et procédure stockée pour annuler une suppression ?


Sujet :

SQL Procédural MySQL

  1. #1
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 402
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 402
    Points : 867
    Points
    867
    Par défaut Trigger et procédure stockée pour annuler une suppression ?
    bonjour,
    j'ai vu que MySQL pouvait faire des triggers et des procédures stockées.
    Je cherche à faire en sorte (dites-moi si c'est faisable ou pas) que quand une requete DELETE est effectuée, alors cette dernière est annulée et remplacer par une requête de type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE matable SET champ_visibilite=false, champ_date_suppression=current_timestamp()  where ID=xxxx ;
    Ainsi, chaque ligne supprimée, sera en fait masquée pour l'utilisateur mais jamais réellement supprimée en base de données.
    Sachant que chaque table a des champs champ_visibilite et champ_date_suppression, je reproduirais le même schéma sur chacune.

    est-ce possible, ça doit être un classique comme utilisation du trigger, non ?
    Si vous avez un très bon tutotriel sur le trigger MySQL et/ou les prco stockées, ce serait gentil de les communiquer.

    Bonne journée

  2. #2
    Membre expérimenté
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 731
    Points : 1 416
    Points
    1 416
    Par défaut
    Bonsoir,

    Les triggers "instead of" ne sont pas encore implémentés dans MySQL.

    Une solution est de passer par un trigger after classique et d'alimenter une table "corbeille" qui contienne les lignes supprimées.
    Pour voir toutes les lignes, dont les supprimées, il faudra créer un vue UNION des 2 tables.

    Pour le coup c'est même mieux car avec un trigger instead of delete sur une table comment faire des purges ?
    mauvaise réponse : "désactiver le trigger, supprimer et réactiver le trigger" car pendant cette opération les autres suppressions ne seront pas loguées
    meilleure réponse : "prévoir dans le trigger une exception, par exemple sur le login, pour pouvoir faire la purge"
    Le savoir est une nourriture qui exige des efforts.

  3. #3
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 402
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 402
    Points : 867
    Points
    867
    Par défaut
    merci je vais tenter une solution.

    j'argumente ta mauvaise solution :
    mauvaise réponse : "désactiver le trigger, supprimer et réactiver le trigger" car pendant cette opération les autres suppressions ne seront pas loguées
    problème impossible avec une option "site en maintenance" assurant que toi seul est connecté.

  4. #4
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 137
    Points : 38 894
    Points
    38 894
    Billets dans le blog
    9
    Par défaut
    Si vous voulez vous prémunir des DELETE, vous pouvez en tout cas n'accorder aucun droit en DELETE aux utilisateurs hors admin

  5. #5
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 384
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 384
    Points : 19 073
    Points
    19 073
    Par défaut
    Salut clavier12AZQSWX.

    Votre raisonnement est mauvais !
    Quand vous demandez la suppression d'une ligne, MySql va vous proposer de le faire. Pourquoi en serait-il autrement ?

    Si vous ne désirez pas de suppressions physiques, mais des suppressions logiques, n'utilisez pas la requête "delete" mais plutôt une procédure stockées.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    --------------
    START TRANSACTION
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE IF NOT EXISTS `base`
            DEFAULT CHARACTER SET `latin1`
            DEFAULT COLLATE       `latin1_general_ci`
    --------------
     
    --------------
    drop table if exists `test`
    --------------
     
    --------------
    CREATE TABLE IF NOT EXISTS `test`
    ( `id`         integer unsigned NOT NULL AUTO_INCREMENT primary key,
      `message`    varchar(255)     NOT NULL,
      `suppress`   char(01)         NOT NULL default 'N'
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    INSERT INTO `test` (`message`) VALUES
      ('un'),('deux'),('trois'),('quatre'),('cinq')
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+---------+----------+
    | id | message | suppress |
    +----+---------+----------+
    |  1 | un      | N        |
    |  2 | deux    | N        |
    |  3 | trois   | N        |
    |  4 | quatre  | N        |
    |  5 | cinq    | N        |
    +----+---------+----------+
    --------------
    delete from `test` where id = 4
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+---------+----------+
    | id | message | suppress |
    +----+---------+----------+
    |  1 | un      | N        |
    |  2 | deux    | N        |
    |  3 | trois   | N        |
    |  5 | cinq    | N        |
    +----+---------+----------+
    --------------
    commit
    --------------
     
    --------------
    DROP PROCEDURE IF EXISTS suppress
    --------------
     
    --------------
    CREATE PROCEDURE `suppress` (IN In_id integer)
    DETERMINISTIC
    NO SQL
    BEGIN
      UPDATE `test` SET suppress='Y' WHERE id=IN_id;
    END
    --------------
     
    --------------
    call suppress(2)
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+---------+----------+
    | id | message | suppress |
    +----+---------+----------+
    |  1 | un      | N        |
    |  2 | deux    | Y        |
    |  3 | trois   | N        |
    |  5 | cinq    | N        |
    +----+---------+----------+
    --------------
    COMMIT
    --------------
     
    Appuyez sur une touche pour continuer...
    Comme on peut le voir dans cet exemple, la ligne a supprimer a été marqué à 'Y'.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  6. #6
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 402
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 402
    Points : 867
    Points
    867
    Par défaut
    Citation Envoyé par Artemus24 Voir le message
    Salut clavier12AZQSWX.

    Votre raisonnement est mauvais !
    Quand vous demandez la suppression d'une ligne, MySql va vous proposer de le faire. Pourquoi en serait-il autrement ?

    Si vous ne désirez pas de suppressions physiques, mais des suppressions logiques, n'utilisez pas la requête "delete" mais plutôt une procédure stockées.
    L'IHM rudimentaire côté user (je ne peux pas donner le nom) ne me permet pas de mettre un bouton lançant la procédure stockée ni même une autre requête SQL, juste une instruction de delete. C'est pour cela que la partie suppression logique ne peut être faite que au niveau mysql dans mon cas.
    bien sûr si ça n'avait tenu qu'à moi j'aurai mis un bouton vers un code php qui execute un update directement voire mieux un insert dans une table copycat "poubelle" comme suggérée plus haut.

    merci Artemus pour votre proposition de code, elle est très instructive.

    bonne journée

  7. #7
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 384
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 384
    Points : 19 073
    Points
    19 073
    Par défaut
    Salut clavier12AZQSWX.

    Votre point de départ est la requête de suppression "delete from ..." et rien d'autre.
    Dans ce cas, il est indispensable de passer par un déclencheur. On ne peut pas faire autrement.
    Sauf qu'en l'état, MySql interdit les astuces pour contourner l'interdiction de modifier la lignes que vous désirez supprimer physiquement.
    Mais on peut interdire la suppression physique de cette même ligne, en utilisant "signal".

    J'ai pensé à plusieurs solutions, comme appeler une procédure stockée, faire des requête dynamique, ou encore encapsuler la requête.
    Rien n'y fait, cela ne fonctionne pas.

    Comme le dit Michel.Priori, les triggers "instead of" ne sont pas implémentés dans MySQL, et c'est dommage.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  8. #8
    Membre confirmé Avatar de isabelle.letrong
    Femme Profil pro
    Conseil - Consultante en systèmes d'information
    Inscrit en
    Juillet 2010
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Conseil - Consultante en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Juillet 2010
    Messages : 109
    Points : 487
    Points
    487
    Par défaut
    Bonjour,

    Il est possible de mettre en place un tel mécanisme d'inhibition d'une mise à jour ou d'un delete, suivi d'un traitement complémentaire.
    Il faut procéder de la manière suivante :

    • Le code applicatif doit être en procédure stockée (malheureusement trop peu pratiqué),
    • On se met en mode transactionnel,
    • Le prologue de la procédure stockée commence par un 'savepoint'
    • Le contrôle du delete se fait via un trigger qui inhibe le delete en lançant une exception
    • Dans son handler d'exception, la procédure stockée délinquante qui aurait invoqué à tort le delete commence par un rollback to savepoint suivi de l'appel d'une procédure stockée qui traite spécifiquement cette exception et fait éventuellement les mises à jour demandées, voire logue l’événement.


    Cela suppose donc de mettre en place une architecture de développement appropriée (adieu le php qui invoque directement le sql....)

  9. #9
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 402
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 402
    Points : 867
    Points
    867
    Par défaut
    merci pour cette proposition et le temps passé à la rédiger....
    mais j'ai effectué une autre méthode "plus simple" .
    -dans la table j'ai ajouté un champs "visbilité" oui/non tinyint default à 1
    -dans l'ihm, j'ai appelé ce même champ "à supprimer" (1=non, 0=oui) derriere les radio button
    -l'ihm remplie l'écran avec une filtre "visibilité=1"
    les salariés sont formés, maintenant s'ils veulent supprimer qqchose, ils doivent l'indiquer explicitement en tournant ce flag.

    ensuite à un autre endroit, je rapporte (pour un cadre) tout ce que les salariés ont demandé à supprimer. et ce cadre lui, a un vrai bouton supprimer.

  10. #10
    Membre confirmé Avatar de isabelle.letrong
    Femme Profil pro
    Conseil - Consultante en systèmes d'information
    Inscrit en
    Juillet 2010
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Conseil - Consultante en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Juillet 2010
    Messages : 109
    Points : 487
    Points
    487
    Par défaut
    Juste une remarque.
    Vous avez effectivement trouvé une réponse applicative mais le contrôle se fait uniquement dans une application et une seule.
    Les routines stockées permettent de maîtriser ces contrôles directement au niveau du SGBDR, donc de se protéger de toute mise à jour demandée par un client quelconque...

    Mais vous pouvez parfaitement estimer que cela est acceptable dans votre contexte

Discussions similaires

  1. Lancer une procédure stockée pour toute une liste
    Par riomois85 dans le forum Développement
    Réponses: 2
    Dernier message: 16/05/2012, 17h51
  2. Procédure stockée pour créer une table.
    Par Khaoula.85 dans le forum Langage SQL
    Réponses: 19
    Dernier message: 13/03/2009, 20h15
  3. procédure stocké pour backuper une table
    Par zaki_1982 dans le forum Administration
    Réponses: 4
    Dernier message: 08/01/2009, 09h14
  4. Réponses: 2
    Dernier message: 22/10/2008, 13h14
  5. Procédure stockée pour restaurer une base
    Par nixonne dans le forum Développement
    Réponses: 2
    Dernier message: 19/08/2008, 12h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo