Skillnaderna kan vara subtila, ibland viktiga och ibland faktiskt obefintliga.
I allmänhet förbereds en förberedd sats 1. med servern (SQL tolkas, exekveringsplan genereras, etc.), 2. exekveras med de ytterligare parametrarna, och sedan 3. stängs. Det låter dig återanvända samma SQL med olika parametrar som skickas in varje gång, det kan hjälpa till att skydda mot SQL-injektion, kan ge vissa prestandaförbättringar (drivrutins-/protokollspecifika, YMMV) och förhindra upprepade steg, som vid generering av exekveringsplaner och SQL-parsning i den förbereder steg ovan.
För någon som skriver källkod kan en förberedd sats vara bekvämare än att sammanfoga strängar och skicka dem till DB-servern.
DB.Query()
metoden tar SQL som en sträng och noll eller fler argument (liksom Exec()
, eller QueryRow()
). En SQL-sträng utan ytterligare argument kommer att fråga exakt vad du skrev. Men förutsatt en SQL-sträng med platshållare och ytterligare argument, görs en förberedd sats åt dig under huven.
DB.Prepare()
metod utför explicit en förberedd sats, som du sedan skickar argument till, som i:stmt.Exec(...args)
.
Det finns ett par saker som är värda att tänka på, när det gäller skillnaderna mellan de två och varför man ska använda det ena eller det andra.
Du kan använda DB.Query()
utan argument. Detta kan vara mycket effektivt eftersom det kan kringgå prepare --> execute --> close sekvens som det förberedda uttalandet nödvändigtvis går igenom.
Du kan också använda den med ytterligare argument och platshållare i frågesträngen, och den kommer att köra en förberedd sats under täcket som jag nämnde ovan. Det potentiella problemet här är att när du gör ett antal frågor, resulterar var och en i ett förberett uttalande under huven. Eftersom det finns extra steg inblandade kan detta vara ganska ineffektivt eftersom det återförbereds, körs och stängs varje gång du gör den frågan.
Med en explicit förberedd sats kan du möjligen undvika den ineffektiviteten när du försöker återanvända den SQL som du tidigare förberedde, med potentiellt andra argument.
Men det fungerar inte alltid som man kan förvänta sig... På grund av den underliggande anslutningspoolen som hanteras av db/sql är din "databasanslutning" ganska virtuell. DB.Prepare()
Metoden kommer att förbereda satsen mot en viss anslutning och sedan försöka få tillbaka samma anslutning när det är dags att köra, men om den anslutningen inte är tillgänglig kommer den helt enkelt att ta tag i en som är tillgänglig och återförbereda och köra mot den. Om du använder samma förberedda uttalande om och om igen kan du, omedvetet, också förbereda det om och om igen. Detta kommer uppenbarligen mest fram när du har att göra med tung trafik.
Så uppenbarligen vilken du använder för vilken omständighet beror på ditt specifika användningsfall, men jag hoppas att detaljerna ovan hjälper dig att förtydliga tillräckligt för att du kan fatta det bästa beslutet i varje fall.
Uppdatera
Med tanke på uppdateringen i OP är det i princip ingen skillnad när frågan bara behöver utföras en gång, eftersom frågor med argument görs som förberedda påståenden bakom kulisserna.
Använd de direkta metoderna, t.ex. DB.Query()
och dess analoger, jämfört med att explicit använda förberedda uttalanden, eftersom det kommer att resultera i något enklare källkod.
Eftersom förberedda uttalanden, i det här fallet, används av säkerhetsskäl, kan det vara värt ansträngningen att hantera säkerhetsproblemen på andra sätt och använda rentextfrågor istället, eftersom det kommer att förbättra prestandan. Eventuella vinster kan dock vara irrelevanta om det inte finns tillräckligt med trafik (eller trafiken förutspås växa avsevärt i framtiden) för att göra det nödvändigt att minska belastningen på servern. Återigen handlar det om det verkliga användningsfallet.
För alla som är intresserade av några mätvärden om skillnaden mellan förberedda uttalanden och direkta klartextfrågor finns det en bra artikel här (som också gör ett utmärkt jobb med att förklara mycket av ovanstående).