PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Po co w ogóle używać *DB.exec() lub przygotowanych instrukcji w Golangu?

"Dlaczego w ogóle używać db.Exec()":

To prawda, że ​​możesz użyć db.Exec i db.Query zamiennie, aby wykonać te same instrukcje sql, jednak obie metody zwracają różne typy wyników. Jeśli jest zaimplementowany przez sterownik, wynik zwracany z db.Exec może powiedzieć, ile wierszy zostało objętych zapytaniem, podczas gdy db.Query zamiast tego zwróci obiekt rows.

Na przykład powiedzmy, że chcesz wykonać DELETE i chcesz wiedzieć, ile wierszy zostało przez nią usuniętych. Możesz to zrobić we właściwy sposób:

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)

lub bardziej gadatliwy i obiektywnie droższy sposób:

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)

Jest trzeci sposób, w jaki możesz to zrobić za pomocą kombinacji postgresowych CTE, SELECT COUNT , db.QueryRow i row.Scan ale nie sądzę, aby przykład był konieczny, aby pokazać, jak nierozsądne byłoby podejście, które byłoby w porównaniu z db.Exec .

Kolejny powód do używania db.Exec ponad db.Query jest wtedy, gdy nie zależy Ci na zwróconym wyniku, gdy wystarczy wykonać zapytanie i sprawdzić, czy wystąpił błąd, czy nie. W takim przypadku możesz to zrobić:

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

Z drugiej strony nie możesz (możesz, ale nie powinieneś) tego zrobić:

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

Robiąc to, po krótkiej chwili Twój program wpadnie w panikę z błędem, który mówi coś podobnego do too many connections open . Dzieje się tak, ponieważ odrzucasz zwrócone db.Rows wartość bez wcześniejszego wprowadzenia obowiązkowego Close wywołaj go, a w rezultacie liczba otwartych połączeń wzrośnie i ostatecznie osiągniesz limit serwera.

"czy przygotowane wypowiedzi w Golangu?":

Uważam, że książka, którą zacytowałeś, nie jest poprawna. Przynajmniej dla mnie wygląda na to, czy db.Query wywołanie tworzy nowe przygotowane zestawienie za każdym razem zależy od sterownika, którego używasz.

Zobacz na przykład te dwie sekcje queryDC (niewyeksportowana metoda wywoływana przez db.Query ):bez przygotowanego zestawienia i z przygotowanym zestawieniem.

Niezależnie od tego, czy książka jest poprawna, czy nie, db.Stmt utworzony przez db.Query byłoby, chyba że jest jakieś wewnętrzne buforowanie, wyrzucone po zamknięciu zwróconych Rows obiekt. Jeśli zamiast tego ręcznie wywołasz db.Prepare a następnie buforuj i ponownie użyj zwróconego db.Stmt możesz potencjalnie poprawić wydajność zapytań, które muszą być często wykonywane.

Aby zrozumieć, w jaki sposób przygotowane oświadczenie można wykorzystać do optymalizacji wydajności, zapoznaj się z oficjalną dokumentacją:https://www.postgresql.org/docs/current/static/sql-prepare.html




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. dołącz do dwóch różnych tabel i usuń zduplikowane wpisy

  2. Co to jest skanowanie sterty bitmapowej w planie kwerend?

  3. Jak wypełnić lukę w zabezpieczeniach PostgreSQL

  4. Eksportuj i importuj zrzut tabeli (.sql) za pomocą pgAdmin

  5. Uzyskaj domyślną wartość szeregową po INSERT wewnątrz PL/pgSQL