Ich bin in eine Debatte bei der Arbeit verwickelt und brauche Ratschläge zu möglichen Fallstricken, die ich übersehen könnte.
Stellen Sie sich ein Szenario vor, in dem ein Trigger verwendet wird, um gelöschte Datensätze in eine Überwachungstabelle zu kopieren. Der Trigger verwendet SELECT *. Jeder zeigt und schreit und sagt uns, wie schlimm das ist.
Wenn jedoch eine Änderung an der Struktur der Haupttabelle vorgenommen wird und die Überwachungstabelle übersehen wird, generiert der Auslöser einen Fehler, der die Benutzer darüber informiert, dass die Überwachungstabelle ebenfalls geändert werden muss.
Der Fehler wird beim Testen auf unseren DEV-Servern abgefangen. Wir müssen jedoch sicherstellen, dass die Produktion DEV entspricht, damit wir SELECT * in Produktionssystemen zulassen (nur Trigger).
Meine Frage lautet also: Ich werde dazu gedrängt, SELECT * zu entfernen, aber ich bin mir nicht sicher, wie ich sonst sicherstellen kann, dass wir automatisch Entwicklungsfehler dieser Art, Ideen oder Best Practices erfassen.
Ich habe unten ein Beispiel zusammengestellt:
--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'
UPDATE (Frage umformulieren):
Ich bin ein DBA und muss sicherstellen, dass Entwickler keine schlecht durchdachten Bereitstellungsskripte bereitstellen, indem sie zu unserer Best-Practice-Dokumentation beitragen. SELECT * verursacht einen Fehler in DEV, wenn der Entwickler die Audit-Tabelle übersieht (dies ist ein Sicherheitsnetz), sodass der Fehler früh im Entwicklungsprozess erkannt wird. Aber irgendwo in der SQL-Verfassung - 2. Änderung heißt es "Du sollst SELECT * nicht verwenden". Jetzt gibt es also einen Anstoß, das Sicherheitsnetz loszuwerden.
Wie würden Sie das Sicherheitsnetz ersetzen, oder sollte ich dies als Best Practice für Trigger betrachten?
UPDATE 2: (Lösung)
Vielen Dank für all Ihre Beiträge. Ich bin mir nicht sicher, ob ich eine klare Antwort habe, da dies ein sehr graues Thema zu sein scheint. Gemeinsam haben Sie jedoch Diskussionspunkte bereitgestellt, die unseren Entwicklern helfen können, ihre Best Practice zu definieren.
Vielen Dank Daevin
für Ihren Beitrag. Ihre Antwort liefert die Grundlage für einige Testmechanismen, die unsere Entwickler implementieren können. +1
Vielen Dank CM_Dayton
, Ihre Vorschläge, die zu Best Practices beitragen, können für jeden von Vorteil sein, der Audit-Trigger entwickelt. +1
Vielen Dank ypercube
, Sie haben viel über die Probleme mit Tabellen nachgedacht, bei denen verschiedene Formen von Definitionsänderungen vorgenommen wurden. +1
Abschließend:
Is Select * ok in a tigger?
Ja, es ist eine Grauzone. Folgen Sie nicht blind der Ideologie "Select * is Bad".
Am I asking for Trouble?
Ja, wir fügen Tabellen nicht nur neue Spalten hinzu.
quelle
SELECT *
Faulheit zu, aber da Sie einen legitimen Grund haben, es zu benutzen, ist es grauer als schwarz-weiß. Was sollten Sie versuchen, etwas zu tun , wie diese , aber es nur einstellen , die gleiche Spaltenanzahl nicht hat, sondern dass die Spaltennamen und Datentypen gleich sind (da jemand Typen Daten ändern könnte und immer noch zu Problemen in der db normalerweise nicht gefangen mit IhremSELECT *
'Sicherheitsnetz'.SELECT *
als Sicherheitsnetz zu verwenden, aber es wird nicht alle Fälle erfassen. Zum Beispiel, wenn Sie eine Spalte löschen und erneut hinzufügen. Dadurch wird die Reihenfolge der Spalten geändert, und (sofern nicht alle Spalten vom gleichen Typ sind) die Einfügungen in die Prüftabelle schlagen fehl oder führen aufgrund der impliziten Typkonvertierungen zu Datenverlust.Antworten:
Typischerweise wird es als "faule" Programmierung angesehen.
Da Sie hier speziell zwei Werte in Ihre
TestAudit
Tabelle einfügen , würde ich darauf achten, dass Ihre Auswahl auch genau zwei Werte erhält . Denn wenn dieseTest
Tabelle aus irgendeinem Grund eine dritte Spalte hat oder jemals bekommt, schlägt dieser Trigger fehl.Nicht direkt mit Ihrer Frage verbunden, aber wenn Sie eine Prüftabelle einrichten, würde ich Ihrer
TestAudit
Tabelle auch einige zusätzliche Spalten hinzufügen, um ...Das führt zu einer Abfrage wie:
Auf diese Weise erhalten Sie genau die Spalten, die Sie benötigen, und Sie prüfen, worum es bei dem Überwachungsereignis geht.
quelle
Ich habe Ihre Frage kommentiert, aber ich dachte, ich würde versuchen, tatsächlich eine Codelösung zu präsentieren.
Normalerweise bin ich damit einverstanden
SELECT *
, faul zu sein, aber da Sie einen legitimen Grund haben, es zu verwenden, ist es grauer als schwarz-weiß.Was Sie sollen (meiner Meinung nach ) versuchen, etwas zu tun , wie diese , aber passen Sie die Spaltennamen und Datentypen gleich sind , um sicherzustellen , (da jemand Typen Daten ändern könnte und immer noch zu Problemen in der db normalerweise nicht mit Ihrer gefangen
SELECT *
Sicherheit Netz'.Sie können sogar eine Funktion erstellen, mit der Sie schnell überprüfen können, ob die Überwachungsversion der Tabelle mit der Nicht-Überwachungsversion übereinstimmt:
Das
SELECT ... EXCEPT SELECT ...Audit
zeigt Ihnen, welche Spalten in der Tabelle nicht in der Audit-Tabelle enthalten sind. Sie können sogar die Funktion ändern, um den Namen von Spalten zurückzugeben, die nicht identisch sind, anstatt nur zuzuordnen, ob sie zugeordnet sind oder nicht, oder sogar eine Ausnahme auslösen.Sie können dies dann ausführen, bevor Sie für jede Tabelle in der Datenbank von einem Server
DEV
zuPRODUCTION
Servern wechseln.quelle
Die Anweisung, die den Trigger aufruft, schlägt fehl und der Trigger schlägt fehl. Es ist besser, den Trigger- und Audit-Trail zu dokumentieren, damit Sie die Abfrage so ändern können, dass die Spalten hinzugefügt werden, anstatt das * anzugeben.
Zumindest sollten Sie den Trigger so ändern, dass er beim Protokollieren von Fehlern in einer Tabelle ordnungsgemäß fehlschlägt, und möglicherweise eine Warnung in die Tabelle einfügen, in der der Trigger die Fehler protokolliert.
Dies erinnert auch daran, dass Sie einen Auslöser oder eine Warnung setzen können, wenn jemand die Tabelle ändert und weitere Spalten hinzufügt oder Spalten entfernt, um Sie zu benachrichtigen, den Auslöser anzuhängen.
Ich glaube, dass die Leistung * nichts ändert, sondern nur die Wahrscheinlichkeit von Fehlern in der Zukunft erhöht, wenn sich die Dinge ändern, und auch zu Netzwerklatenz führen kann, wenn Sie bei Bedarf mehr Informationen über das Netzwerk abrufen. Es gibt eine Zeit und einen Ort für *, aber ich denke, wie oben beschrieben, haben Sie bessere Lösungen und Tools, die Sie stattdessen ausprobieren können.
quelle
Wenn sich Ihre ursprüngliche oder Ihre Audit-Tabellenstruktur überhaupt ändert, stellen Sie sicher, dass bei Ihrer Auswahl * ein Problem auftritt.
Wenn sich einer der beiden ändert, tritt ein Fehler auf.
Du könntest es tun:
Aber wie CM_Dayton sagt, ist das faul programmiert und öffnet die Tür für andere Inkonsistenzen. Damit dieses Szenario funktioniert, müssen Sie unbedingt sicherstellen, dass Sie die Struktur beider Tabellen gleichzeitig aktualisieren.
quelle