sql >> Database teknologi >  >> RDS >> PostgreSQL

Hvorfor overhovedet bruge *DB.exec() eller forberedte sætninger i Golang?

"Hvorfor overhovedet bruge db.Exec()":

Det er rigtigt, at du kan bruge db.Exec og db.Query i flæng for at udføre de samme sql-sætninger, men de to metoder returnerer forskellige typer resultater. Hvis det implementeres af driveren, returneres resultatet fra db.Exec kan fortælle dig, hvor mange rækker der blev påvirket af forespørgslen, mens db.Query returnerer rækkeobjektet i stedet.

Lad os f.eks. sige, at du vil udføre en DELETE sætning, og du vil vide, hvor mange rækker der blev slettet af den. Du kan gøre det på den rigtige måde:

res, err := db.Exec(`DELETE FROM my_table WHERE expires_at = $1`, time.Now())
if err != nil {
    panic(err)
}

numDeleted, err := res.RowsAffected()
if err != nil {
    panic(err)
}
print(numDeleted)

eller den mere omfattende og objektivt dyrere måde:

rows, err := db.Query(`DELETE FROM my_table WHERE expires_at = $1 RETURNING *`, time.Now())
if err != nil {
    panic(err)
}
defer rows.Close()

var numDelete int
for rows.Next() {
    numDeleted += 1
}
if err := rows.Err(); err != nil {
    panic(err)
}
print(numDeleted)

Der er en tredje måde du kan gøre dette på med en kombination af postgres CTE'er, SELECT COUNT , db.QueryRow og row.Scan men jeg tror ikke, at et eksempel er nødvendigt for at vise, hvor urimelig en tilgang det ville være sammenlignet med db.Exec .

Endnu en grund til at bruge db.Exec over db.Query er, når du er ligeglad med det returnerede resultat, hvor alt du behøver er at udføre forespørgslen og kontrollere, om der var en fejl eller ej. I et sådant tilfælde kan du gøre dette:

if _, err := db.Exec(`<my_sql_query>`); err != nil {
    panic(err)
}

På den anden side kan du ikke (du kan, men du bør ikke) gøre dette:

if _, err := db.Query(`<my_sql_query>`); err != nil {
    panic(err)
}

Hvis du gør dette, vil dit program efter et kort stykke tid gå i panik med en fejl, der siger noget, der ligner too many connections open . Dette skyldes, at du kasserer de returnerede db.Rows værdi uden først at gøre den obligatoriske Close kalde på det, og så ender du med, at antallet af åbne forbindelser stiger og til sidst rammer serverens grænse.

"eller forberedte udsagn i Golang?":

Jeg tror ikke, den bog, du har citeret, er korrekt. I det mindste for mig ser det ud som om det er en db.Query call opretter en ny forberedt erklæring hver gang afhænger af den driver du bruger.

Se for eksempel disse to sektioner af queryDC (en ikke-eksporteret metode kaldet af db.Query ):uden udarbejdet erklæring og med udarbejdet erklæring.

Uanset om bogen er korrekt eller ej en db.Stmt oprettet af db.Query ville blive smidt væk, medmindre der er intern caching i gang, efter du har lukket de returnerede Rows objekt. Hvis du i stedet manuelt kalder db.Prepare og derefter cache og genbrug den returnerede db.Stmt du kan potentielt forbedre ydeevnen af ​​de forespørgsler, der skal udføres ofte.

For at forstå, hvordan en udarbejdet erklæring kan bruges til at optimere ydeevnen, kan du tage et kig på den officielle dokumentation:https://www.postgresql.org/docs/current/static/sql-prepare.html




  1. Første offentlige forhåndsvisning af SQL Server 2019:CTP 2.0

  2. Hvordan man erklærer input-output-parametre i SQL Server Stored Procedure/-funktion?

  3. Oprettelse af strengindeks med kode først

  4. Hvordan genererer jeg en CREATE TABLE-sætning for en given tabel i SQL Server?