sql >> Database teknologi >  >> RDS >> Mysql

golang sql-driverens forberedelseserklæring

Forskellene kan være subtile, nogle gange vigtige og nogle gange faktisk ikke-eksisterende.

Generelt bliver en forberedt sætning 1. forberedt med serveren (SQL parset, eksekveringsplan genereret osv.), 2. udføres med de yderligere parametre, og derefter 3. lukkes. Det lader dig genbruge den samme SQL med forskellige parametre, der sendes ind hver gang, det kan hjælpe med at beskytte mod SQL-injektion, kan give nogle ydeevneforbedringer (driver/protokolspecifik, YMMV) og forhindre gentagne trin, som i generering af eksekveringsplan og SQL-parsing i forbered trin ovenfor.

For nogen, der skriver kildekode, kan en forberedt sætning være mere praktisk end at sammenkæde strenge og sende dem til DB-serveren.

DB.Query() metode tager SQL som en streng og nul eller flere argumenter (det samme gør Exec() , eller QueryRow() ). En SQL-streng uden yderligere argumenter vil forespørge på præcis det, du skrev. Men forudsat en SQL-streng med pladsholdere og yderligere argumenter, bliver der lavet en forberedt erklæring for dig under hætten.

DB.Prepare() metoden udfører eksplicit en forberedt sætning, som du derefter sender argumenter til, som i:stmt.Exec(...args) .

Der er et par ting, der er værd at tænke over, hvad angår forskellene mellem de to, og hvorfor man skal bruge det ene eller det andet.

Du kan bruge DB.Query() uden argumenter. Dette kan være meget effektivt, da det kan omgå prepare --> execute --> close rækkefølge, som den forberedte erklæring nødvendigvis gennemgår.

Du kan også bruge det med yderligere argumenter og pladsholdere i forespørgselsstrengen, og det vil udføre en forberedt erklæring under coveret, som jeg nævnte ovenfor. Det potentielle problem her er, at når du laver et antal forespørgsler, resulterer hver af dem i en forberedt erklæring. Da der er ekstra trin involveret, kan dette være ret ineffektivt, da det genforbereder, udføres og lukkes, hver gang du foretager den forespørgsel.

Med en eksplicit forberedt erklæring kan du muligvis undgå denne ineffektivitet, da du forsøger at genbruge den SQL, du tidligere har forberedt, med potentielt forskellige argumenter.

Men det går ikke altid, som man kunne forvente... På grund af den underliggende forbindelsespulje, der styres af db/sql, er din "databaseforbindelse" ret virtuel. DB.Prepare() metoden vil forberede sætningen mod en bestemt forbindelse og derefter forsøge at få den samme forbindelse tilbage, når det er tid til at udføre, men hvis den forbindelse er utilgængelig, vil den simpelthen hente en, der er tilgængelig og genforberede og udføre mod den. Hvis du bruger den samme forberedte erklæring igen og igen, kan du, ubevidst, også forberede den igen og igen. Dette kommer tydeligvis mest frem, når du har at gøre med tung trafik.

Så det afhænger selvfølgelig af, hvilken situation du skal bruge til, men jeg håber, at ovenstående detaljer hjælper dig med at tydeliggøre nok for dig til, at du kan træffe den bedste beslutning i hvert enkelt tilfælde.

Opdater

Givet opdateringen i OP er der stort set ingen forskel, når forespørgslen kun skal udføres én gang, da forespørgsler med argumenter udføres som forberedte udsagn bag kulisserne.

Brug de direkte metoder, f.eks. DB.Query() og dets analoger, kontra eksplicit at bruge forberedte udsagn, da det vil resultere i en noget enklere kildekode.

Da forberedte erklæringer, i dette tilfælde, bliver brugt af sikkerhedsmæssige årsager, kan det være besværet værd at håndtere sikkerhedsproblemerne på andre måder og bruge almindelige tekstforespørgsler i stedet, da det vil forbedre ydeevnen. Eventuelle gevinster kan dog være irrelevante, medmindre der er tilstrækkelig trafik (eller trafikken forventes at vokse betydeligt i fremtiden) til at det er nødvendigt at lette belastningen på serveren. Igen kommer det ned til den virkelige verden.

For alle, der er interesseret i nogle målinger om forskellen mellem forberedte udsagn og direkte forespørgsler i klartekst, er der en god artikel her (som også gør et fremragende stykke arbejde med at forklare meget af ovenstående).



  1. Beregning af den samlede mængde udstyr for et datointerval

  2. Hvordan forespørger man efter null-værdier i json-felttypen postgresql?

  3. Rum - Brug af eksterne SQLites samt intern DB

  4. Hvornår skal jeg lukke mysqli (database) forbindelse?