Sono coinvolto in un dibattito sul lavoro e ho bisogno di alcuni consigli su possibili insidie che potrei trascurare.
Immagina uno scenario in cui viene utilizzato un trigger per copiare i record eliminati in una tabella di controllo. Il trigger utilizza SELECT *. Tutti indicano e gridano e ci dicono quanto sia brutto.
Tuttavia, se viene apportata una modifica alla struttura della tabella principale e la tabella di controllo viene trascurata, il trigger genererà un errore che consente alle persone di sapere che anche la tabella di controllo deve essere modificata.
L'errore verrà rilevato durante i test sui nostri server DEV. Ma dobbiamo garantire che DEVIA corrisponda alla produzione, quindi consentiamo SELECT * nei sistemi di produzione (solo trigger).
Quindi la mia domanda è: mi viene spinto a rimuovere SELECT *, ma non sono sicuro di come altro per garantire che stiamo acquisendo automaticamente errori di sviluppo di questa natura, qualche idea o questa è la migliore pratica?
Ho messo un esempio qui sotto:
--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'
AGGIORNAMENTO (riformula domanda):
Sono un DBA e devo assicurarmi che gli sviluppatori non forniscano script di implementazione poco ponderati contribuendo alla nostra documentazione sulle migliori pratiche. SELECT * provoca un errore in DEV quando lo sviluppatore trascura la tabella di audit (questa è una rete di sicurezza), quindi l'errore viene rilevato all'inizio del processo di sviluppo. Ma da qualche parte nella Costituzione SQL - 2 ° emendamento si legge "Non utilizzare SELECT *". Quindi ora c'è una spinta per sbarazzarsi della rete di sicurezza.
Come sostituiresti la rete di sicurezza o dovrei considerare questa come la migliore pratica per i trigger?
AGGIORNAMENTO 2: (soluzione)
Grazie per tutto il tuo contributo, non sono sicuro di avere una risposta chiara perché sembra essere un argomento molto grigio. Ma collettivamente hai fornito punti di discussione che possono aiutare i nostri sviluppatori ad andare avanti nel definire le loro migliori pratiche.
Grazie Daevin
per il tuo contributo, la tua risposta fornisce le basi per alcuni meccanismi di test che i nostri sviluppatori possono implementare. +1
Grazie CM_Dayton
, i tuoi suggerimenti che contribuiscono alle migliori pratiche possono essere utili per chiunque stia sviluppando Audit Trigger. +1
Grazie mille ypercube
, hai sollevato molte riflessioni sulle questioni relative alle tabelle che subiscono diverse forme di modifica delle definizioni. +1
In conclusione:
Is Select * ok in a tigger?
Sì, è un'area grigia, non seguire ciecamente l'ideologia "Seleziona * è cattivo".
Am I asking for Trouble?
Sì, facciamo molto di più che aggiungere nuove colonne alle tabelle.
SELECT *
essere pigro, ma poiché hai un motivo legittimo per usarlo è più grigio che in bianco e nero. Che cosa si dovrebbe provare a fare è qualcosa di simile questo , ma regolarlo avere non solo lo stesso numero di colonne, ma che i nomi delle colonne e tipi di dati sono gli stessi (dal momento che qualcuno potrebbe cambiare i tipi di dati e ancora causare problemi nel db normalmente non catturati con la tua SELECT *
"rete di sicurezza".
SELECT *
come rete di sicurezza, ma non catturerà tutti i casi. Ad esempio, se si rilascia una colonna e la si aggiunge di nuovo. Ciò cambierà l'ordine delle colonne e (a meno che tutte le colonne non siano dello stesso tipo) gli inserimenti nella tabella di controllo falliranno o comporteranno la perdita di dati a causa delle conversioni di tipo implicite.