Je conçois généralement mes bases de données en suivant les règles suivantes:
- Personne d'autre que db_owner et sysadmin n'a accès aux tables de la base de données.
- Les rôles utilisateur sont contrôlés au niveau de la couche application. J'utilise généralement un rôle db pour accorder l'accès aux vues, aux procédures stockées et aux fonctions, mais dans certains cas, j'ajoute une deuxième règle pour protéger certaines procédures stockées.
- J'utilise TRIGGERS pour valider initialement les informations critiques.
CREATE TRIGGER <TriggerName>
ON <MyTable>
[BEFORE | AFTER] INSERT
AS
IF EXISTS (SELECT 1
FROM inserted
WHERE Field1 <> <some_initial_value>
OR Field2 <> <other_initial_value>)
BEGIN
UPDATE MyTable
SET Field1 = <some_initial_value>,
Field2 = <other_initial_value>
...
END
- DML est exécuté à l'aide de procédures stockées:
sp_MyTable_Insert(@Field1, @Field2, @Field3, ...);
sp_MyTable_Delete(@Key1, @Key2, ...);
sp_MyTable_Update(@Key1, @Key2, @Field3, ...);
Pensez-vous que, dans ce scénario, cela vaut la peine d'utiliser les CONTRAINTES PAR DÉFAUT, ou j'ajoute un travail supplémentaire et inutile au serveur de base de données?
Mise à jour
Je comprends qu'en utilisant la contrainte DEFAULT, je donne plus d'informations à quelqu'un d'autre qui doit administrer la base de données. Mais je m'intéresse surtout à la performance.
Je suppose que la base de données vérifie toujours les valeurs par défaut, même si je fournis la valeur correcte, donc je fais le même travail deux fois.
Par exemple, existe-t-il un moyen d'éviter la contrainte DEFAULT dans une exécution de déclencheur?
sql-server
ettsql
comme le code dans votre question est très spécifique à ce SGBDRéponses:
Pourquoi supposeriez-vous cela? ;-). Étant donné que les valeurs par défaut existent pour fournir une valeur lorsque la colonne à laquelle elles sont attachées n'est pas présente dans la
INSERT
déclaration, je suppose que c'est exactement le contraire: qu'elles sont complètement ignorées si la colonne associée est présente dans laINSERT
déclaration.Heureusement, aucun de nous n'a à supposer quoi que ce soit en raison de cette déclaration dans la question:
Les questions sur les performances sont presque toujours testables. Il nous suffit donc de proposer un test pour permettre à SQL Server (la véritable autorité ici) de répondre à cette question.
INSTALLER
Exécutez la commande suivante une fois:
Exécutez les tests 1A et 1B individuellement, pas ensemble car cela biaise le timing. Exécutez chacun plusieurs fois pour avoir une idée de la durée moyenne de chacun.
Test 1A
Test 1B
Exécutez les tests 2A et 2B individuellement, pas ensemble car cela biaise le timing. Exécutez chacun plusieurs fois pour avoir une idée de la durée moyenne de chacun.
Test 2A
Test 2B
Vous devriez voir qu'il n'y a pas de réelle différence de timing entre les tests 1A et 1B, ou entre les tests 2A et 2B. Donc, non, il n'y a pas de pénalité de performance pour avoir un
DEFAULT
défini mais pas utilisé.De plus, en plus de simplement documenter le comportement prévu, vous devez garder à l'esprit que c'est surtout vous qui vous souciez que les instructions DML soient complètement contenues dans vos procédures stockées. Les gens de soutien s'en moquent. Les futurs développeurs pourraient ne pas être conscients de votre désir d'avoir tous les DML encapsulés dans ces procédures stockées, ou s'en soucier même s'ils le savent. Et quiconque maintient cette base de données après votre départ (soit un autre projet ou un autre travail) peut ne pas s'en soucier, ou ne pas être en mesure d'empêcher l'utilisation d'un ORM, peu importe combien ils protestent. Par conséquent, les valeurs par défaut peuvent aider en ce sens qu'elles donnent aux gens un "out" lors de la réalisation d'un
INSERT
, en particulier un ad-hocINSERT
effectué par un représentant du support, car il s'agit d'une colonne qu'ils n'ont pas besoin d'inclure (c'est pourquoi j'utilise toujours les valeurs par défaut lors de l'audit). colonnes de date).ET, il m'est venu à l'esprit qu'il peut être montré de manière assez objective si oui ou non
DEFAULT
est vérifiée lorsque la colonne associée est présente dans l'INSERT
instruction: fournissez simplement une valeur non valide. Le test suivant fait exactement cela:Comme vous pouvez le voir, lorsqu'une colonne (et une valeur, pas le mot-clé
DEFAULT
) est fournie, la valeur par défaut est 100% ignorée. Nous le savons parce que celaINSERT
réussit. Mais si la valeur par défaut est utilisée, il y a une erreur car elle est finalement en cours d'exécution.Bien qu'il soit nécessaire d'éviter les contraintes par défaut (au moins dans ce contexte), pour des raisons d'exhaustivité, on peut noter qu'il ne serait possible "d'éviter" une contrainte par défaut dans un
INSTEAD OF
déclencheur, mais pas dans unAFTER
déclencheur. Selon la documentation de CREATE TRIGGER :Bien sûr, l'utilisation d'un
INSTEAD OF
déclencheur nécessiterait:AFTER
déclencheur qui active la contrainteCependant, je ne recommanderais pas exactement cela.
la source
CURRENT_TIMESTAMP
des colonnes datetime. Ainsi, le test «facile» d'utilisation d'une expression invalide ne fonctionnera pas là (et une valeur invalide ne peut pas être utilisée dans leCREATE TABLE
car elle est validée), et je n'ai pas le temps de construire le test de performance. Mais je soupçonne que la plupart des SGBDR les traiteraient de la même manière.Je ne vois aucun inconvénient majeur à avoir des contraintes par défaut. En fait, je vois un avantage particulier - vous avez défini la valeur par défaut au même niveau de logique que la définition de table elle-même. Si vous avez une valeur par défaut que vous fournissez dans votre procédure stockée, quelqu'un doit y aller pour savoir quelle est la valeur par défaut; et, ce n'est pas quelque chose qui serait évident pour quelqu'un de nouveau dans le système, nécessairement (si, par exemple, vous héritez d'un milliard de dollars demain, achetez votre propre île tropicale, quittez et déménagez là-bas, laissant une autre mauvaise sève pour comprendre les choses) par eux-mêmes).
la source