Question

Supposons que ma table de base de données comporte une colonne timedate de la dernière mise à jour ou insertion. Ce qui serait préférable:

  1. Demander à un déclencheur de mettre à jour le champ.
  2. Demandez au programme qui effectue l'insertion / la mise à jour de définir le champ.

La première option semble être la plus facile car je n'ai même pas besoin de recompiler pour le faire, mais ce n'est pas vraiment un gros problème. En dehors de cela, j'ai du mal à trouver une raison de faire l'un par rapport à l'autre. Des suggestions?

Était-ce utile?

La solution

La première option peut être plus robuste car la base de données maintiendra le champ. Cela vient avec la surcharge possible d'utiliser des déclencheurs.

Si vous pouviez avoir d'autres applications écrivant dans cette table à l'avenir, via leurs propres interfaces, j'utiliserais un déclencheur pour que vous ne répétiez pas cette logique ailleurs.

Si votre application est à peu près ce qu'elle est, ou si d'autres applications accéderaient à la base de données via le même calque de données, j'éviterais ce cauchemar que les déclencheurs peuvent induire et mettre la logique directement dans votre calque de données (SQL, ORM, processus stockés , etc.).

Bien sûr, vous devez vous assurer que votre source de temps (votre application, les ordinateurs de vos utilisateurs, votre serveur SQL) est exacte dans les deux cas.

Concernant les raisons pour lesquelles je n'aime pas les déclencheurs:

Peut-être que j'étais téméraire en les traitant de cauchemar. Comme tout le reste, ils sont appropriés avec modération. Si vous les utilisez pour des choses très simples comme celle-ci, je pourrais y participer.

C'est lorsque le code de déclenchement devient complexe (et coûteux) que les déclencheurs commencent à causer beaucoup de problèmes. Ils sont une taxe cachée sur chaque requête d'insertion / mise à jour / suppression que vous exécutez (selon le type de déclencheur). Si cette taxe est acceptable, ils peuvent être le bon outil pour le travail.

Autres conseils

Vous n'avez pas mentionné 3. Utilisez une procédure stockée pour mettre à jour la table. La procédure permet de définir les horodatages à votre guise.

Peut-être que ce n'est pas faisable pour vous, mais je ne l'ai pas vu mentionné.

Je dirais que déclencher au cas où quelqu'un utiliserait autre chose que votre application pour mettre à jour la table, vous voudriez probablement aussi avoir un LastUpdatedBy et utiliser SUSER_SNAME () pour cela, ainsi vous pourrez voir qui a fait la mise à jour

Tant que j'utilise un SGBD dans lequel j'ai confiance en les déclencheurs, j'utilise toujours l'option de déclencheur. Il permet au SGBD de s’occuper du maximum de choses, ce qui est généralement une bonne chose.

Cela fonctionne, assurez-vous dans tous les cas que la colonne timestamp ait la valeur correcte. Les frais généraux seraient négligeables.

La seule chose qui serait contre les déclencheurs est la portabilité. Si ce n’est pas un problème, je ne pense pas que la direction à prendre soit posée.

Je suis un partisan des procédures stockées pour tout. Votre procédure de mise à jour peut contenir un GETDATE () pour la colonne.

Et je n'aime pas les déclencheurs de ce type de mise à jour. Le manque de visibilité des déclencheurs a tendance à semer la confusion.

Cela me semble une logique commerciale ... Je serais plus disposé à mettre cela dans le code. Laissez la base de données gérer le stockage des données ... Ni plus ni moins.

Les déclencheurs sont une bénédiction et une malédiction.

Bénédiction: vous pouvez les utiliser pour activer toutes sortes de vérifications de contraintes et de gestion de données personnalisées sans connaissance ni modification des systèmes backend.

Malédiction: Vous ne savez pas ce qui se passe derrière votre dos. Problèmes de concurrence / impasses par des objets supplémentaires introduits dans des transactions inattendues. Comportement fantôme, y compris les modifications de l’environnement de la session et les relevés de rangs peu fiables. Déclenchement excessif de conditions. Pénalités supplémentaires pour points chauds / performances.

La réponse à cette question (les dates de mise à jour implicitement (déclencheur) ou explicitement (code)) pèse généralement lourdement sur le contexte. Par exemple, si vous utilisez la date de la dernière modification comme champ informatif, vous souhaiterez peut-être la modifier uniquement lorsqu'un "utilisateur" apporte des modifications importantes à une ligne par rapport à un processus automatisé qui met simplement à jour une sorte de marqueur interne qui ne tient pas à l'utilisateur .

Si vous utilisez le déclencheur pour la synchronisation des modifications ou si vous n'avez aucun contrôle sur le code qui exécute un déclencheur, cela a beaucoup plus de sens.

Mon conseil sur la gâchette, utilisez-le pour faire attention. La plupart des systèmes vous permettent de filtrer l'exécution en fonction de l'opération et des champs modifiés. L'utilisation appropriée des déclencheurs "avant" ou "après" peut avoir un impact significatif sur les performances.

Enfin, quelques systèmes sont capables d’exécuter un seul déclencheur sur plusieurs modifications (plusieurs lignes effectuées dans une transaction). Votre code doit être prêt à s’appliquer lui-même comme une mise à jour en bloc de plusieurs lignes.

Normalement, je dirais de le faire côté base de données, mais cela dépend de votre application. Si vous utilisez LINQ-to-SQL, vous pouvez simplement définir le champ comme Horodatage et demander à votre DAL d'utiliser le champ Horodatage pour la simultanéité. Il le gère automatiquement pour vous, donc avoir à répéter du code est un non-événement.

Si vous écrivez vous-même votre DAL, alors je serais plus susceptible de gérer cela du côté base de données car cela rend l'écriture d'interfaces utilisateur beaucoup plus flexible - bien que, je le ferais probablement dans une procédure stockée qui a " public " accès et tables verrouillées - vous ne voulez pas que n'importe quel clown vienne et contourne votre procédure stockée en écrivant directement dans les tables ... sauf si vous envisagez de faire de votre DAL un composant autonome que toute application future devra utiliser pour accéder au base de données, auquel cas, vous pouvez la coder directement dans le DAL - bien sûr, vous ne devez le faire que si vous pouvez garantir que tous les utilisateurs accédant à la base de données le font via votre composant DAL.

Si vous autorisez l'option "public". accès à la base de données à insérer dans les tables, vous devrez alors utiliser le déclencheur, sinon tout le monde pourra insérer / mettre à jour un seul champ de la table et le champ mis à jour ne pourra jamais être mis à jour.

Je voudrais que la date soit conservée dans la base de données, c'est-à-dire un déclencheur, une procédure stockée, etc. Dans la plupart de vos applications pilotées par une base de données, l'application utilisateur ne sera pas le seul moyen par lequel les utilisateurs professionnels accèdent aux données. . Il existe des outils de reporting, des extraits, le code utilisateur SQL, etc. Il existe également des mises à jour et des corrections effectuées par l'administrateur de base de données pour lesquelles l'application ne fournira pas la date.

Mais honnêtement, la principale raison pour laquelle je ne le ferais pas à partir de l'application est que vous n'avez aucun contrôle sur la date / l'heure sur l'ordinateur client. Ils pourraient peut-être revenir en arrière pour obtenir plus de jours d'une licence d'évaluation de quelque chose ou simplement vouloir faire de mauvaises choses à votre programme.

Vous pouvez le faire sans le déclencheur si votre base de données prend en charge les valeurs par défaut des champs. Par exemple, dans SQL Server 2005, j'ai une table avec un champ créé comme ceci:

create table dbo.Repository
   (
    ...
   last_updated     datetime default getdate(),
    ...
   )

alors le code d'insertion laisse simplement ce champ en dehors de la liste de champs d'insertion.

J'ai oublié que cela ne fonctionnait que pour la première insertion - j'ai également un déclencheur de mise à jour, pour mettre à jour les champs de date et mettre une copie de l'enregistrement mis à jour dans ma table d'historique - que je publierais ... mais l'éditeur continue à me tromper sur mon code ...

Enfin:

create trigger dbo.Repository_Upd on dbo.Repository instead of update
as
--**************************************************************************
--   Trigger: Repository_Upd
--    Author: Ron Savage
--      Date: 09/28/2008
--
-- Description:
-- This trigger sets the last_updated and updated_by fields before the update
-- and puts a copy of the updated row into the Repository_History table.
--
-- Modification History:
-- Date        Init  Comment
-- 10/22/2008  RS    Blocked .prm files from updating the history as they
--                   get updated every time the cfg file is run.
-- 10/21/2008  RS    Updated the insert into the history table to use the
--                   d.last_updated field from the Repository table rather
--                   than getdate() to avoid micro second differences.
-- 09/28/2008  RS    Created.
--**************************************************************************
begin
   --***********************************************************************
   -- Update the record but fill in the updated_by, updated_system and
   -- last_updated date with current information.
   --***********************************************************************
   update cr set
      cr.filename           = i.filename,
      cr.created_by         = i.created_by,
      cr.created_system     = i.created_system,
      cr.create_date        = i.create_date,
      cr.updated_by         = user,
      cr.updated_system     = host_name(),
      cr.last_updated       = getdate(),
      cr.content            = i.content
   from
      Repository cr

      JOIN Inserted i
         on (i.config_id = cr.config_id);


   --***********************************************************************
   -- Put a copy in the history table
   --***********************************************************************
   declare @extention varchar(3);
   select @extention = lower(right(filename,3)) from Inserted;

   if (@extention <> 'prm')
      begin
      Insert into Repository_History
         select
            i.config_id,
            i.filename,
            i.created_by,
            i.created_system,
            i.create_date,
            user           as updated_by,
            host_name()    as updated_system,
            d.last_updated,
            d.content
         from
            Inserted i

            JOIN Repository d
               on (d.config_id = i.config_id);
      end
end

Ron

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top