Je suis pris dans un débat au travail et j'ai besoin de conseils sur les pièges que je pourrais ignorer.
Imaginez un scénario dans lequel un déclencheur est utilisé pour copier des enregistrements supprimés dans une table d'audit. Le déclencheur utilise SELECT *. Tout le monde pointe et crie et nous dit à quel point c'est mauvais.
Cependant, si une modification est apportée à la structure de la table principale et que la table d'audit est ignorée, le déclencheur générera une erreur permettant aux utilisateurs de savoir que la table d'audit doit également être modifiée.
L'erreur sera détectée lors des tests sur nos serveurs DEV. Mais nous devons nous assurer que les correspondances de production DEV, nous autorisons donc SELECT * dans les systèmes de production (déclencheurs uniquement).
Donc, ma question est: on me pousse à supprimer le SELECT *, mais je ne sais pas comment garantir que nous capturons automatiquement les erreurs de développement de cette nature, des idées ou est-ce la meilleure pratique?
J'ai rassemblé un exemple ci-dessous:
--Create Test Table
CREATE TABLE dbo.Test(ID INT IDENTITY(1,1), Person VARCHAR(255))
--Create Test Audit Table
CREATE TABLE dbo.TestAudit(AuditID INT IDENTITY(1,1),ID INT, Person VARCHAR(255))
--Create Trigger on Test
CREATE TRIGGER [dbo].[trTestDelete] ON [dbo].[Test] AFTER DELETE
NOT FOR REPLICATION
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.TestAudit([ID], [Person])
SELECT *
FROM deleted
END
--Insert Test Data into Test
INSERT INTO dbo.Test VALUES
('Scooby')
,('Fred')
,('Shaggy')
--Perform a delete
DELETE dbo.Test WHERE Person = 'Scooby'
MISE À JOUR (reformuler la question):
Je suis un DBA et je dois m'assurer que les développeurs ne fournissent pas de scripts de déploiement mal pensés en contribuant à notre documentation des meilleures pratiques. SELECT * provoque une erreur dans DEV lorsque le développeur ignore la table d'audit (il s'agit d'un filet de sécurité), de sorte que l'erreur est détectée au début du processus de développement. Mais quelque part dans la Constitution SQL - 2ème amendement, il est écrit "Tu ne dois pas utiliser SELECT *". Il y a donc maintenant un effort pour se débarrasser du filet de sécurité.
Comment remplacer le filet de sécurité ou devrais-je considérer que c'est la meilleure pratique pour les déclencheurs?
MISE À JOUR 2: (solution)
Merci pour toutes vos contributions, je ne suis pas sûr d'avoir une réponse claire car cela semble être un sujet très gris. Mais collectivement, vous avez fourni des points de discussion qui peuvent aider nos développeurs à avancer dans la définition de leurs meilleures pratiques.
Merci Daevin
pour votre contribution, votre réponse fournit les bases de certains mécanismes de test que nos développeurs peuvent implémenter. +1
Merci CM_Dayton
, vos suggestions contribuant aux meilleures pratiques peuvent être utiles à toute personne qui développe des déclencheurs d'audit. +1
Merci ypercube
beaucoup, vous avez beaucoup réfléchi aux problèmes concernant les tables subissant différentes formes de modifications de définition. +1
En conclusion:
Is Select * ok in a tigger?
Oui, c'est une zone grise, ne suivez pas aveuglément l'idéologie "Select * is Bad".
Am I asking for Trouble?
Oui, nous faisons plus que simplement ajouter de nouvelles colonnes aux tableaux.
SELECT *
être paresseux, mais puisque vous avez une raison légitime de l'utiliser, c'est plus gris que noir et blanc. Ce que vous devriez essayer de faire est quelque chose comme ça , mais ajustez-le non seulement pour avoir le même nombre de colonnes, mais aussi pour que les noms de colonnes et les types de données soient les mêmes (car quelqu'un pourrait changer les types de données et toujours causer des problèmes dans la base de données qui ne sont pas normalement interceptés avec votre SELECT *
«filet de sécurité»
SELECT *
comme filet de sécurité, mais elle n'attrapera pas tous les cas. Par exemple, si vous déposez une colonne et l'ajoutez à nouveau. Cela modifiera l'ordre des colonnes et (sauf si toutes les colonnes sont du même type), les insertions dans la table d'audit échoueront ou entraîneront une perte de données en raison des conversions implicites de types.