7
votes

Une contrainte SQL peut-elle être utilisée pour empêcher une valeur particulière étant modifiée lorsqu'une condition détient?

Je sais que les contraintes SQL peuvent forcer des données à respecter les critères de validité. Cependant, qu'en est-il des critères tels que «Grade de l'étudiant ne peut être mis à jour que lorsque le drapeau« finalisé »est faux»? Ces critères de mise à jour doivent-ils être gérés par l'application?


2 commentaires

Selon votre SGBDM, vous pouvez l'appliquer avec un "avant" ou "au lieu de" déclencher sur la table.


Ce que Joe a dit Joe, bien que les contraintes de chèques puissent également être utilisées, en fonction de la base de données.


3 Réponses :


-3
votes

imo, je dirais que cela devrait être fait dans l'application ou la procédure stockée (éventuellement à la fois), plutôt que comme une contrainte réelle (entre autres choses, dans votre exemple spécifique, une note "finalisée" " t toujours signifie que c'est en fait final).

Toutefois, si j'étais implémentant cela comme une contrainte, j'utiliserais une contrainte de contrôle (à nouveau, à l'aide de votre exemple) P>

CONSTRAINT chk_grade CHECK(grade between 0 AND 100 and finalized = 0)


3 commentaires

Comment cela éviterait-il les mises à jour de noter lorsque le drapeau finalisé est défini? Cela n'empêche-t-il pas que le drapeau finalisé d'être défini? Je ne pense pas que c'est ce que l'OP a en tête.


Je devrais vérifier la syntaxe (comme je l'ai mentionné), mais ce qu'il / devrait / faire / faire est vérifiant que finalisé = 0 (c'est-à-dire qu'il est "faux") avant de permettre une gamme de 0 à 100 à placer dans note


Cela ne fonctionne pas (dans SQL Server, de toute façon) car la vérification échoue lorsque vous essayez de transformer «finalisé» à 1.



4
votes

Un déclencheur, une contrainte et une colonne supplémentaire.

à partir de la fin: p>

  1. La colonne supplémentaire stocke la valeur qui doit être "corrigée": p>

    CREATE TRIGGER StudentsFinaliseGrade
    ON Students AFTER INSERT, UPDATE
    AS
    IF UPDATE(Grade)
      UPDATE Students
      SET SavedGrade = i.Grade
      FROM inserted i
      WHERE i.ID = Students.ID
        AND i.Grade <> i.SavedGrade
    
  2. La contrainte limite la modification de la colonne code> code>: p>

    ALTER TABLE Students
    ADD CONSTRAINT CK_Grade CHECK (Finalised = 'false' OR Grade = SavedGrade)
    
  3. La gâchette met à jour la colonne supplémentaire lorsque la colonne code> code> est mise à jour (ce qui suit est pour SQL Server): P>

    ALTER TABLE ADD SavedGrade int
    


0 commentaires

5
votes

Réponse courte: Non, les contraintes SQL ne peuvent pas empêcher en elles-mêmes une modification de la grade de colonne lorsque finalisée est «vraie» (mais laissez un changement sinon).

Il y a Plusieurs types de contraintes SQL : check, défaut, non null , Clé unique, clé primaire et clé étrangère.

Chacun de ceux-ci peut limiter ou affecter les valeurs des colonnes, soit seuls, soit en combinaison, mais ne peut pas empêcher une mise à jour des valeurs autorisées. En particulier, aucune de ces contraintes ne peut empêcher une mise à jour de grade et / ou de finalisée en fonction des valeurs précédentes de grade et finalisées.

Un déclencheur de mise à jour peut faire ceci: comparez les nouvelles et les anciennes valeurs de grade, et si elles diffèrent et finalisées = «true», annulez la mise à jour avec un message d'erreur explicatif.

Cependant, l'application peut et devrait appliquer de manière plus gracieuse une telle "règle d'entreprise". La règle elle-même pourrait utiliser un peu de clarification sur lorsque la valeur finalisée peut être modifiée. E.G., est-il autorisé à changer de grade et défini finalisé = 'faux' en même temps? La logique de déclenchement peut gérer de tels détails et il serait raisonnable d'installer cela comme un échec de sécurité, tout en rendant les règles explicites quelque part dans l'application (frontal / middleware / backend).


0 commentaires