Le differenze possono essere sottili, talvolta importanti e talvolta effettivamente inesistenti.
In generale un'istruzione preparata 1. viene preparata con il server (analisi SQL, piano di esecuzione generato, ecc.), 2. viene eseguita con i parametri aggiuntivi e quindi 3. viene chiusa. Ti consente di riutilizzare lo stesso SQL con parametri diversi passati ogni volta, può aiutare a prevenire l'iniezione di SQL, può fornire alcuni miglioramenti delle prestazioni (specifici per driver/protocollo, YMMV) e prevenire passaggi ripetuti, come nella generazione del piano di esecuzione e nell'analisi SQL in il preparare passaggio sopra.
Per qualcuno che scrive codice sorgente, un'istruzione preparata può essere più conveniente che concatenare stringhe e inviarle al server DB.
Il DB.Query()
accetta SQL come stringa e zero o più argomenti (come fa Exec()
o QueryRow()
). Una stringa SQL senza argomenti aggiuntivi interrogherà esattamente ciò che hai scritto. Tuttavia, fornita una stringa SQL con segnaposto e argomenti aggiuntivi, viene eseguita un'istruzione preparata per te sotto il cofano.
Il DB.Prepare()
il metodo esegue esplicitamente un'istruzione preparata, a cui poi si passano argomenti, come in:stmt.Exec(...args)
.
Ci sono un paio di cose su cui vale la pena pensare, in termini di differenze tra i due e perché usare l'uno o l'altro.
Puoi usare DB.Query()
senza argomenti. Questo può essere molto efficiente poiché può ignorare prepara --> esegui --> chiudi sequenza che l'istruzione preparata attraversa necessariamente.
Puoi anche usarlo con argomenti aggiuntivi e segnaposto nella stringa di query ed eseguirà un'istruzione preparata sotto le coperte come ho menzionato sopra. Il potenziale problema qui è che quando si effettuano una serie di query, ciascuna risulta in una dichiarazione preparata in modo nascosto. Dal momento che sono coinvolti passaggi aggiuntivi, questo può essere piuttosto inefficiente in quanto si ri-prepara, esegue e si chiude ogni volta che si esegue quella query.
Con un'istruzione preparata esplicita puoi eventualmente evitare quell'inefficienza mentre stai tentando di riutilizzare l'SQL che hai preparato in precedenza, con argomenti potenzialmente diversi.
Ma non sempre funziona come ci si potrebbe aspettare... A causa del pool di connessioni sottostante gestito da db/sql, la tua "connessione al database" è abbastanza virtuale. Il DB.Prepare()
il metodo preparerà l'istruzione rispetto a una particolare connessione e quindi proverà a ripristinare la stessa connessione quando è il momento di eseguirla, ma se quella connessione non è disponibile ne prenderà semplicemente una disponibile e la ri-preparerà ed eseguirà contro quella. Se stai usando la stessa dichiarazione preparata più e più volte, potresti, inconsapevolmente, anche prepararla più e più volte. Questo ovviamente viene alla luce soprattutto quando hai a che fare con un traffico intenso.
Quindi, ovviamente, quale uso in quale circostanza dipende dal tuo caso d'uso specifico, ma spero che i dettagli sopra ti aiutino a chiarirti abbastanza da poter prendere la decisione migliore in ogni caso.
Aggiorna
Dato l'aggiornamento in OP, essenzialmente non c'è differenza quando la query deve essere eseguita solo una volta, poiché le query con argomenti vengono eseguite come istruzioni preparate dietro le quinte.
Utilizzare i metodi diretti, ad es. DB.Query()
e i suoi analoghi, rispetto all'utilizzo esplicito di istruzioni preparate, poiché risulterà in un codice sorgente in qualche modo più semplice.
Poiché le istruzioni preparate, in questo caso, vengono utilizzate per motivi di sicurezza, potrebbe valere la pena di gestire i problemi di sicurezza con altri mezzi e utilizzare invece query di testo in chiaro, poiché migliorerà le prestazioni. Eventuali guadagni, tuttavia, potrebbero essere irrilevanti a meno che non vi sia traffico sufficiente (o si prevede che il traffico aumenterà considerevolmente in futuro) da rendere necessario un alleggerimento del carico sul server. Ancora una volta si tratta del caso d'uso del mondo reale.
Per chiunque sia interessato ad alcune metriche sulla differenza tra dichiarazioni preparate e query dirette in chiaro, c'è un buon articolo qui (che fa anche un ottimo lavoro nello spiegare gran parte di quanto sopra).