cpp

MySQL. Получение записей

При использовании SQL-команды SELECT запросы выполняются с помощью метода Query(). Формат метода:

(*sql.DB).Query(query string, args ...interface{}) (*sql.Rows, error)

В первом параметре указывается SQL-запрос, а в последующих параметрах можно передать значения, которые будут подставлены в SQL-запрос вместо знаков вопросов. Метод возвращает два значения. Через первое значение доступен указатель на объект sql.Rows, с помощью которого можно получить результат. Через второе значение доступен объект ошибки или значение nil, если операция выполнена успешно. Пример:

rows, err := db.Query("SELECT * FROM `rubr`")
if err != nil {
   fmt.Fprintln(os.Stderr, err)
   return
}

Структура sql.Rows содержит следующие методы:

  • Close() — закрывает набор данных. Формат метода:
(*sql.Rows).Close() error

Пример:

defer rows.Close()
  • Columns() — позволяет получить слайс с названиями полей. Формат метода:
(*sql.Rows).Columns() ([]string, error)

Пример:

fmt.Println(rows.Columns()) // [id_rubr name_rubr] <nil>
  • ColumnTypes() — позволяет получить слайс информацией о полях. Формат метода:
(*sql.Rows).ColumnTypes() ([]*sql.ColumnType, error)

Пример вывода названий полей:

arr, err := rows.ColumnTypes()
for _, v := range arr {
   fmt.Println(v.Name())
}
  • Err() — возвращает объект ошибки при ее возникновении во время итерации или значение nil. Формат метода:
(*sql.Rows).Err() error
  • Next() — переходит к следующей записи и возвращает значение true, если запись доступна для получения методом Scan(). Функция возвращает значение false, если записей больше нет или возникла ошибка, которую можно получить с помощью метода Err(). Формат метода:
(*sql.Rows).Next() bool
  • Scan() — позволяет получить результат. Перед вызовом этого метода нужно вызвать метод Next(). Формат метода:
(*sql.Rows).Scan(dest ...interface{}) error

В качестве параметров указываются адреса переменных, в которые будут записаны данные. Количество параметров должно совпадать с количеством полей. Функция возвращает объект ошибки или значение nil, если операция выполнена успешно. Пример:

rubr := Rubr{}
for rows.Next() {
   err := rows.Scan(&rubr.id, &rubr.name)
   if err != nil {
      fmt.Fprintln(os.Stderr, err)
      continue
   }
   fmt.Println(rubr.id, rubr.name)
}
  • NextResultSet() — возвращает значение true, если доступен дополнительный набор, и false — в противном случае. Формат метода:
(*sql.Rows).NextResultSet() bool

Выведем содержимое таблицы rubr, отсортировав названия рубрик по возрастанию (листинг 16.5).

Листинг 16.5. Получение записей

package main

import (
   "database/sql"
   "fmt"
   "os"

   _ "github.com/go-sql-driver/mysql"
)

type Rubr struct {
   id   int
   name string
}

func main() {
   db, err := sql.Open("mysql", "root:@/godb")
   if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
   }
   defer db.Close()
   rows, err := db.Query("SELECT * FROM `rubr` ORDER BY `name_rubr`")
   if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
   }
   defer rows.Close()
   fmt.Println(rows.Columns()) // [id_rubr name_rubr] <nil>
   arr, err := rows.ColumnTypes()
   for _, v := range arr {
      fmt.Println(v.Name())
   }
   rubr := Rubr{}
   for rows.Next() {
      err := rows.Scan(&rubr.id, &rubr.name)
      if err != nil {
         fmt.Fprintln(os.Stderr, err)
         continue
      }
      fmt.Println(rubr.id, rubr.name)
   }
   if err = rows.Err(); err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
   }
}

Результат:

C:\book\packages>go run main.go
[id_rubr name_rubr] <nil>
id_rubr
name_rubr
2 Музыка
3 Поисковые порталы
1 Программирование

Если используется подготовленный запрос, то следует воспользоваться методом Query() структуры sql.Stmt. Формат метода:

(*sql.Stmt).Query(args ...interface{}) (*sql.Rows, error)

В параметрах можно передать значения, которые будут подставлены в SQL-запрос вместо знаков вопросов. Метод возвращает два значения. Через первое значение доступен указатель на объект sql.Rows, с помощью которого можно получить результат. Через второе значение доступен объект ошибки или значение nil, если операция выполнена успешно.

Пример использования метода Query() приведен в листинге 16.6.

Листинг 16.6. Метод Query() структуры sql.Stmt

package main

import (
   "database/sql"
   "fmt"
   "os"

   _ "github.com/go-sql-driver/mysql"
)

type Result struct {
   url   string
   title string
   name  string
   email string
}

func main() {
   db, err := sql.Open("mysql", "root:@/godb")
   if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
   }
   defer db.Close()
   stmt, err := db.Prepare(
      "SELECT `site`.`url` AS `site_url`, " +
      "`site`.`title` AS `site_title`, " +
      "`rubr`.`name_rubr` AS `rubr_name`, " +
      "`user`.`email` AS `user_email` " +
      "FROM `site`, `rubr`, `user` " +
      "WHERE `site`.`id_rubr`=`rubr`.`id_rubr` " +
      "AND `site`.`id_user`=`user`.`id_user` " +
      "AND `user`.`id_user`=?")
   if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
   }
   defer stmt.Close()
   rows, err := stmt.Query(1)
   if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
   }
   defer rows.Close()
   fmt.Println(rows.Columns())
   // [site_url site_title rubr_name user_email] <nil>
   result := Result{}
   for rows.Next() {
      err := rows.Scan(&result.url, &result.title, &result.name,
                       &result.email)
      if err != nil {
         fmt.Fprintln(os.Stderr, err)
         continue
      }
      fmt.Println(result.url, result.title, result.name,
                  result.email)
   }
   if err = rows.Err(); err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
   }
}

Результат:

[site_url site_title rubr_name user_email] <nil>
https://python.org Python Программирование user1@mail.ru
https://google.ru Гугль Поисковые порталы user1@mail.ru

Если SQL-запрос возвращает только одну запись, например, делается выборка по идентификатору, то можно воспользоваться методом QueryRow(). Формат метода:

(*sql.DB).QueryRow(query string, args ...interface{}) *sql.Row

В первом параметре указывается SQL-запрос, а в последующих параметрах можно передать значения, которые будут подставлены в SQL-запрос вместо знаков вопросов. Метод возвращает указатель на объект sql.Row, который не может быть нулевым.

При использовании подготовленных запросов формат метода QueryRow() структуры sql.Stmt выглядит так:

(*sql.Stmt).QueryRow(args ...interface{}) *sql.Row

В параметрах можно передать значения, которые будут подставлены в SQL-запрос вместо знаков вопросов. Метод возвращает указатель на объект sql.Row, который не может быть нулевым.

Структура sql.Row содержит два метода:

  • Err() — возвращает объект ошибки или значение nil. Формат метода:
(*sql.Row).Err() error
  • Scan() — позволяет получить результат. Формат метода:
(*sql.Row).Scan(dest ...interface{}) error

В качестве параметров указываются адреса переменных, в которые будут записаны данные. Количество параметров должно совпадать с количеством полей. Функция возвращает объект ошибки или значение nil, если операция выполнена успешно.

Пример использования метода QueryRow() приведен в листинге 16.7.

Листинг 16.7. Метод QueryRow()

package main

import (
   "database/sql"
   "fmt"
   "os"

   _ "github.com/go-sql-driver/mysql"
)

func main() {
   db, err := sql.Open("mysql", "root:@/godb")
   if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
   }
   defer db.Close()
   query := "SELECT `name_rubr` FROM `rubr` WHERE `id_rubr`=?"
   name := ""
   err = db.QueryRow(query, 1).Scan(&name)
   if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
   }
   fmt.Println(name)
   stmt, err := db.Prepare(query)
   if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
   }
   defer stmt.Close()
   err = stmt.QueryRow(2).Scan(&name)
   if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
   }
   fmt.Println(name)
}

Учебник Go (Golang)
Учебник Go (Golang) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов

cpp