Domanda

In passato non sono mai stato un fan dell'utilizzo dei trigger sulle tabelle del database.Per me hanno sempre rappresentato una sorta di "magia" che sarebbe avvenuta sul lato del database, molto lontano dal controllo del codice della mia applicazione.Volevo anche limitare la quantità di lavoro che il DB doveva svolgere, poiché generalmente è una risorsa condivisa e ho sempre pensato che i trigger potessero diventare costosi in scenari di carico elevato.

Detto questo, ho trovato un paio di casi in cui aveva senso utilizzare i trigger (almeno secondo me avevano senso).Recentemente, però, mi sono trovato in una situazione in cui a volte potrei aver bisogno di "bypassare" il trigger.Mi sono sentito davvero in colpa nel dover cercare modi per farlo, e penso ancora che una migliore progettazione del database allevierebbe la necessità di questo bypass.Sfortunatamente questo DB è utilizzato da più applicazioni, alcune delle quali sono gestite da un team di sviluppo molto poco collaborativo che urlava di modifiche allo schema, quindi sono rimasto bloccato.

Qual è il consenso generale là fuori sui trigger?Li ami?Li odi?Pensi che servano a uno scopo in alcuni scenari?Pensi che avere la necessità di bypassare un trigger significhi che stai "facendo qualcosa di sbagliato"?

È stato utile?

Soluzione

I trigger vengono generalmente utilizzati in modo errato, introducono bug e pertanto devono essere evitati. Non progettare mai un trigger per eseguire il controllo del vincolo di integrità che attraversa le righe in una tabella (ad es. & Quot; lo stipendio medio per reparto non può superare X).

Tom Kyte , VP di Oracle ha indicato che preferirebbe rimuove i trigger come funzionalità del database Oracle a causa del loro ruolo frequente nei bug . Sa che è solo un sogno, e i trigger sono qui per rimanere, ma se potesse rimuoverà i trigger da Oracle, lo farebbe (insieme alla clausola WHEN OTHERS e alle transazioni autonome).

  

I trigger possono essere utilizzati correttamente? Assolutamente.

     

Il problema è che non vengono usati correttamente   molti casi che sarei disposto a dare   qualsiasi beneficio percepito solo per ottenere   sbarazzarsi degli abusi (e dei bug) causati da   loro. - Tom Kyte

Altri suggerimenti

Pensa a un database come a un grande oggetto di grandi dimensioni: dopo ogni chiamata, dovrebbe essere in uno stato logicamente coerente.

I database si espongono tramite tabelle e mantenere coerenti tabelle e righe con i trigger. Un altro modo per mantenerli coerenti è impedire l'accesso diretto alle tabelle e consentirlo solo attraverso procedure e viste memorizzate.

L'aspetto negativo dei trigger è che qualsiasi azione può invocarli; anche questo è un punto di forza: nessuno rovinerà l'integrità del sistema attraverso l'incompetenza.

Come contrappunto, consentire l'accesso a un database solo tramite stored procedure e viste consente comunque l'accesso backdoor delle autorizzazioni. Gli utenti con autorizzazioni sufficienti hanno la certezza di non violare l'integrità del database, tutti gli altri usano le procedure memorizzate.

Per quanto riguarda la riduzione della quantità di lavoro: i database sono incredibilmente efficienti quando non hanno a che fare con il mondo esterno; saresti davvero sorpreso di quanto anche il cambio di processo danneggi le prestazioni. Questo è un altro aspetto positivo delle procedure memorizzate: piuttosto che una dozzina di chiamate al database (e tutti i round trip associati), ce n'è uno.

  

Raggruppare le cose in un singolo proc memorizzato va bene, ma cosa succede quando qualcosa va storto? Supponi di avere 5 passaggi e che il primo passaggio non riesca, cosa succede agli altri passaggi? Devi aggiungere un sacco di logica lì dentro per soddisfare quella situazione. Una volta che inizi a farlo, perdi i vantaggi della procedura memorizzata in quello scenario.

La logica aziendale deve andare da qualche parte e ci sono molte regole di dominio implicite incorporate nella progettazione di un database: relazioni, vincoli e così via sono un tentativo di codificare le regole di business dicendo, ad esempio, che un utente può avere solo una password. Dato che hai iniziato a spingere le regole di business sul server di database avendo queste relazioni e così via, dove traccia la linea? Quando il database rinuncia alla responsabilità per l'integrità dei dati e inizia a fidarsi delle app chiamanti e degli utenti del database per farlo correttamente? Le procedure memorizzate con queste regole incorporate in esse possono spingere molto potere politico nelle mani dei DBA. Dipende da quanti livelli esisteranno nella tua architettura n-tier; se esiste un livello di presentazione, business e dati, dove sta la separazione tra business e dati? Quale valore aggiunto aggiunge il livello aziendale? Eseguirai il livello aziendale sul server database come stored procedure?

Sì, penso che dover bypassare un trigger significhi che stai "sbagliando"; in questo caso un trigger non fa per te.

inserisci qui la descrizione dell

Lavoro con le app web e winforms in c # e HATE si innesca con passione. Non ho mai incontrato una situazione in cui potrei giustificare l'uso di un trigger per spostare quella logica nel livello aziendale dell'applicazione e replicare lì la logica di trigger.

Non faccio alcun tipo di lavoro DTS o qualcosa del genere, quindi potrebbero esserci alcuni casi d'uso per usare il trigger lì, ma se qualcuno in uno dei miei team dice che potrebbero voler usare un trigger, è meglio che abbiano preparato i loro argomenti bene perché mi rifiuto di stare in piedi e lasciare che i trigger vengano aggiunti a qualsiasi database su cui sto lavorando.

Alcuni motivi per cui non mi piacciono i trigger:

  • Spostano la logica nel database. Una volta che inizi a farlo, stai chiedendo un mondo di dolore perché perdi il debug, la sicurezza del tempo di compilazione, il flusso logico. È tutto in discesa.
  • La logica che implementano non è facilmente visibile a nessuno.
  • Non tutti i motori di database supportano i trigger, quindi la tua soluzione crea dipendenze dai motori di database

Sono sicuro che potrei pensare a più motivi dalla parte superiore della mia testa, ma quelli da soli sono sufficienti per non usare i grilletti.

" Non progettare mai un trigger per eseguire il controllo del vincolo di integrità che attraversa le righe in una tabella " - Non posso essere d'accordo. La domanda è contrassegnata con "SQL Server" e le clausole CHECK vincoli in SQL Server non possono contenere una sottoquery; peggio, l'implementazione sembra avere un presupposto "hard coded" che un CHECK coinvolgerà solo una singola riga, quindi l'utilizzo di una funzione non è affidabile. Quindi, se ho bisogno di un vincolo che coinvolge legittimamente più di una riga - e un buon esempio qui è la chiave primaria in sequenza in una classica tabella temporale 'tempo valido' in cui devo prevenire periodi di sovrapposizione per la stessa entità - come posso Lo faccio senza grilletto? Ricorda che questa è una chiave primaria, qualcosa per garantire che io abbia l'integrità dei dati, quindi farla rispettare ovunque tranne che nel DBMS è fuori discussione. Fino a quando i vincoli CHECK non ottengono subquery, non vedo un'alternativa all'utilizzo dei trigger per determinati tipi di vincoli di integrità.

I trigger possono essere molto utili. Possono anche essere molto pericolosi. Penso che vadano bene per le attività di pulizia della casa come la compilazione di dati di audit (creati da, data modificata, ecc.) E in alcuni database possono essere utilizzati per l'integrità referenziale.

Ma non sono un grande fan di mettere molta logica aziendale in loro. Questo può rendere problematico il supporto perché:

  • è un ulteriore livello di codice da ricercare
  • a volte, come ha appreso l'OP, quando è necessario eseguire una correzione dei dati, il trigger potrebbe fare le cose supponendo che la modifica dei dati avvenga sempre tramite una direttiva dell'applicazione e non da uno sviluppatore o DBA che risolve un problema, o addirittura da un'altra app

Per quanto riguarda il dover bypassare un trigger per fare qualcosa, potrebbe significare che stai facendo qualcosa di sbagliato, oppure potrebbe significare che il trigger sta facendo qualcosa di sbagliato.

La regola generale che mi piace usare con i trigger è di mantenerli leggeri, veloci, semplici e il più invasivi possibile.

Mi ritrovo a bypassare i trigger durante l'importazione di dati in blocco. Penso che sia giustificato in tali circostanze.

Se finisci per bypassare molto spesso i trigger, probabilmente dovrai dare un'altra occhiata a cosa li metti lì in primo luogo.

In generale, voterei per "servono a uno scopo in alcuni scenari". Sono sempre nervoso per le implicazioni sulle prestazioni.

Non sono un fan, personalmente. Li userò, ma solo quando rileverò un collo di bottiglia nel codice che può essere eliminato spostando le azioni in un trigger. In generale, preferisco la semplicità e un modo per mantenere le cose semplici è mantenere la logica in un posto: l'applicazione. Ho anche lavorato su lavori in cui l'accesso è molto compartimentato. In quegli ambienti, più codice inserisco, più persone devo impegnare anche per le correzioni più semplici.

Ho usato i trigger per la prima volta un paio di settimane fa. Siamo passati da un server di produzione da SQL 2000 a SQL 2005 e abbiamo scoperto che i driver si comportavano diversamente con i campi NText (memorizzazione di un documento XML di grandi dimensioni), eliminando l'ultimo byte. Ho usato un trigger come correzione temporanea per aggiungere un byte fittizio aggiuntivo (uno spazio) alla fine dei dati, risolvendo il nostro problema fino a quando non sarebbe stata implementata una soluzione adeguata.

Oltre a questo caso speciale e temporaneo, direi che li eviterei poiché nascondono ciò che sta succedendo e la funzione che forniscono dovrebbe essere gestita esplicitamente dallo sviluppatore piuttosto che come magia nascosta.

Sinceramente l'unica volta che utilizzo i trigger per simulare un indice univoco a cui è consentito avere NULL che non conta per l'unicità.

  

Per quanto riguarda la riduzione della quantità di lavoro: i database sono incredibilmente efficienti quando non hanno a che fare con il mondo esterno; saresti davvero sorpreso di quanto anche il cambio di processo danneggi le prestazioni. Questo è un altro aspetto positivo delle procedure memorizzate: piuttosto che una dozzina di chiamate al database (e tutti i round trip associati), ce n'è uno.

questo è un po 'fuori tema, ma dovresti anche essere consapevole che lo stai guardando solo da un potenziale positivo.

Raggruppare le cose in un singolo proc memorizzato va bene, ma cosa succede quando qualcosa va storto? Supponi di avere 5 passaggi e che il primo passaggio non riesca, cosa succede agli altri passaggi? Devi aggiungere un sacco di logica lì dentro per soddisfare quella situazione. Una volta che inizi a farlo, perdi i vantaggi della procedura memorizzata in quello scenario.

Fan totale,

ma devo usarlo con parsimonia quando,

  • È necessario mantenere la coerenza (soprattutto quando le tabelle delle dimensioni vengono utilizzate in un magazzino e dobbiamo mettere in relazione i dati nella tabella dei fatti con la loro dimensione corretta. A volte, la riga corretta nella tabella delle dimensioni può essere molto costosa calcola in modo che tu voglia che la chiave sia scritta direttamente nella tabella dei fatti, un buon modo per mantenere quella "relazione" è con il trigger.

  • È necessario registrare le modifiche (ad esempio in una tabella di controllo, è utile sapere quale utente @@ ha apportato la modifica e quando si è verificato)

Alcuni RDBMS come sql server 2005 forniscono anche trigger su istruzioni CREATE / ALTER / DROP (in modo da poter sapere chi ha creato quale tabella, quando, trascinato quale colonna, quando, ecc.)

Onestamente, usando i trigger in quei 3 scenari, non vedo perché dovresti mai aver bisogno di "disabilitare" " loro.

La regola generale è: non usare i trigger. Come accennato in precedenza, aggiungono sovraccarico e complessità che possono essere facilmente evitati spostando la logica fuori dal livello DB.

Inoltre, in MS SQL Server, i trigger vengono attivati ??una volta per comando sql e non per riga. Ad esempio, la seguente istruzione sql eseguirà il trigger una sola volta.

UPDATE tblUsers
SET Age = 11
WHERE State = 'NY'

Molte persone, incluso me stesso, avevano l'impressione che i grilletti fossero attivati ??su ogni riga, ma non è così. Se hai un'istruzione sql come quella sopra che può cambiare i dati in più di una riga, potresti voler includere un cursore per aggiornare tutti i record interessati dal trigger. Puoi vedere come questo può essere contorto molto rapidamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top