Frage

Angenommen, ich habe eine Datenbanktabelle, in der eine Timedate -Spalte des letzten Mals aktualisiert oder eingefügt wurde. Das wäre vorzuziehen:

  1. Haben Sie ein Trigger -Aktualisierung des Feldes.
  2. Lassen Sie das Programm, das das Einfügen/Update durchführt, das Feld festgelegt.

Die erste Option scheint die einfachste zu sein, da ich nicht einmal neu kompilieren muss, aber das ist nicht wirklich eine große Sache. Ansonsten habe ich Probleme, an irgendwelche Gründe zu denken, einen übereinander zu tun. Irgendwelche Vorschläge?

War es hilfreich?

Lösung

Die erste Option kann robuster sein, da die Datenbank das Feld verwaltet. Dies kommt mit dem möglichen Aufwand der Verwendung von Triggern.

Wenn Sie andere Apps in Zukunft über ihre eigenen Schnittstellen in diese Tabelle schreiben könnten, würde ich mit einem Auslöser gehen, damit Sie diese Logik nirgendwo anders wiederholen.

Wenn Ihre App so gut wie IT ist oder andere Apps über denselben DataLayer auf die Datenbank zugreifen würden, würde ich vermeiden, dass der Albtraum die Logik direkt in Ihre DataLayer (SQL, ORM, gespeicherte Procs usw. einfügen kann. ).

Natürlich müssen Sie sicherstellen, dass Ihre Zeitquelle (Ihre App, die PCs Ihrer Benutzer, Ihr SQL-Server) in beiden Fällen korrekt ist.


In Bezug auf warum ich keine Auslöser mag:

Vielleicht war ich vorschnell, indem ich sie einen Albtraum nannte. Wie alles andere sind sie in Maßen angemessen. Wenn Sie sie für sehr einfache Dinge wie diese verwenden, könnte ich an Bord gehen.

Wenn der Triggercode komplex (und teuer) wird, verursachen die Auslöser viele Probleme. Sie sind eine versteckte Steuer für jede von Ihnen ausgeführte Einfügungs-/Aktualisierungs-/Löschenabfrage (abhängig vom Typ des Triggers). Wenn diese Steuer akzeptabel ist, können sie das richtige Instrument für den Job sein.

Andere Tipps

Sie haben nicht erwähnt 3. Verwenden Sie eine gespeicherte Prozedur, um die Tabelle zu aktualisieren. Die Prozedur kann die Zeitstempel wie gewünscht einstellen.

Vielleicht ist das für Sie nicht machbar, aber ich habe es nicht erwähnt gesehen.

Ich würde sagen, dass Trigger nur für den Fall, dass jemand als Ihre App etwas verwendet, um die Tabelle zu aktualisieren

Solange ich ein DBMS verwende, in dessen Triggern ich vertraue, würde ich immer mit der Triggeroption gehen. Es ermöglicht den DBMs, sich um so viele Dinge wie möglich zu kümmern, was normalerweise eine gute Sache ist.

Es funktioniert unter allen Umständen, dass die Zeitstempelspalte den richtigen Wert hat. Der Overhead wäre vernachlässigbar.

Das einzige, was gegen Trigger wäre, ist die Portabilität. Wenn das kein Problem ist, denke ich nicht, dass es eine Frage gibt, in die man gehen soll.

Ich bin ein Befürworter gespeicherter Verfahren für alles. Ihr Update Proc könnte einen getDate () für die Spalte enthalten.

Und ich mag keine Auslöser für diese Art von Update. Die mangelnde Sichtbarkeit von Triggern verursacht tendenziell Verwirrung.

Das klingt für mich nach Geschäftslogik ... Ich würde es mehr dazu bringen, dies in den Code zu setzen. Lassen Sie die Datenbank die Speicherung von Daten verwalten ... nicht mehr und nicht weniger.

Auslöser sind ein Segen und ein Fluch.

Segen: Sie können sie verwenden, um alle Arten von benutzerdefinierten Einschränkungen und Datenverwaltung ohne Backend -Systemkenntnisse oder -änderungen zu ermöglichen.

Fluch: Sie wissen nicht, was hinter Ihrem Rücken passiert. Parallelitätsprobleme/Deadlocks durch zusätzliche Objekte, die in Transaktionen eingebracht wurden, die nicht ursprünglich erwartet wurden. Phantomverhalten einschließlich Änderungen der Sitzungsumgebung, unzuverlässige Rowcounts. Übermäßige Auslösen der Bedingungen.

Die Antwort auf diese Frage (Update -Daten implizit (Auslöser) oder explizit (Code)) gewichtet nach dem Kontext. Wenn Sie beispielsweise das letzte Änderungsdatum als Informationsfeld verwenden, möchten Sie es möglicherweise nur ändern, wenn ein „Benutzer“ tatsächlich wichtige Änderungen an einer Zeile im Vergleich zu einem automatisierten Prozess vornimmt .

Wenn Sie den Auslöser für die Änderung der Synchronisation verwenden oder keine Kontrolle über Code haben, der einen Auslöser ausführt, macht es viel sinnvoller.

Mein Rat zum Trigger verwenden es, um vorsichtig zu sein. Mit den meisten Systemen können Sie die Ausführung basierend auf dem Betrieb und den Feldern geändert. Die ordnungsgemäße Verwendung von 'vor' vs 'nach' Auslöser kann erhebliche Leistungsauswirkungen haben.

Schließlich können einige Systeme einen einzelnen Auslöser für mehrere Änderungen ausführen (mehrere Zeilen innerhalb einer Transaktion). Ihr Code sollte vorbereitet sein, um sich als Massenaktualisierung auf mehrere Zeilen anzuwenden.

Normalerweise würde ich sagen, dass es sich um Datenbankseite handelt, aber es hängt von Ihrer Anwendung ab. Wenn Sie LINQ-to-SQL verwenden, können Sie das Feld einfach als Zeitstempel festlegen und Ihr DAL das Zeitstempelfeld für die Parallelität verwenden lassen. Es behandelt es für Sie automatisch, daher ist es ein Nicht -Ereignis, Code zu wiederholen.

Wenn Sie Ihren Dal selbst schreiben, würde ich dies eher auf der Datenbankseite verarbeiten, da das Schreiben von Benutzeroberflächen weitaus flexibler wird - obwohl ich dies wahrscheinlich in einem gespeicherten Verfahren tun würde, das "öffentlich" hat " "Zugriff und die Tabellen gesperrt - Sie möchten nicht, dass ein Clown mit dem Weg kommt und Ihre gespeicherte Prozedur umgeht, indem Sie direkt an die Tabellen schreiben ... es sei denn In der Datenbank können Sie sie in diesem Fall direkt in den DAL codieren - natürlich sollten Sie dies nur tun, wenn Sie garantieren können, dass jeder, der auf die Datenbank zugreift, dies über Ihre DAL -Komponente tut.

Wenn Sie den "öffentlichen" Zugriff auf die Datenbank in Tabellen einfügen möchten, müssen Sie sich mit dem Auslöser einfügen, da sonst jemand ein einzelnes Feld in die Tabelle einfügen/aktualisieren kann und das aktualisierte Feld niemals aktualisiert werden kann .

Ich hätte das Datum in der Datenbank, dh einen Auslöser, gespeicherten Prozeduren usw. beibehalten. In den meisten Ihrer datenbankgesteuerten Anwendungen wird die Benutzer-App nicht das einzige Mittel sein, mit dem die Geschäftsbenutzer Daten erhalten. Es gibt Berichterstattungsinstrumente, Extrakte, Benutzer SQL usw. Es gibt auch Aktualisierungen und Korrekturen, die von der DBA durchgeführt werden, für die die Anwendung nicht das Datum angibt.

Aber ehrlich gesagt ist der Grund, warum ich es nicht aus der Anwendung tun würde, dass Sie über das Datum/die Uhrzeit auf dem Client -Computer keine Kontrolle haben. Möglicherweise rollen sie es zurück, um mehr Tage aus einer Testlizenz für etwas herauszukommen, oder möchten möglicherweise nur schlechte Dinge in Ihrem Programm antun.

Sie können dies ohne den Auslöser tun, wenn Ihre Datenbank Standardwerte auf den Feldern unterstützt. In SQL Server 2005 habe ich beispielsweise eine Tabelle mit einem Feld wie folgt erstellt:

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

Dann lässt der Einfügencode dieses Feld nur aus der Feldliste des Einfügens heraus.

Ich habe vergessen, dass nur für den ersten Einfügen funktioniert hat - ich habe auch einen Update -Auslöser, um die Datumsfelder zu aktualisieren und eine Kopie des aktualisierten Datensatzes in meiner Geschichtestabelle zu setzen - die ich posten würde ... aber der Editor wird sich irrt Auf meinem Code ...

Endlich:

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top