Выборка строк в Go
Запрос выборки возвращает набор строк.
Пакет database/sql отдает объект
курсора: его закрывают в отложенном
вызове, затем идут по строкам командой
перехода к следующей и читают столбцы
в переменные.
После цикла смотрят ошибку обхода: сбой на середине пути не всегда виден на последней итерации. Если выборка не открылась, курсор не трогают.
Вставим два товара и выведем их:
package main
import (
"database/sql"
"fmt"
"log"
"os"
_ "modernc.org/sqlite"
)
func main() {
os.Remove("shop.db")
db, err := sql.Open("sqlite", "shop.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(`
CREATE TABLE goods (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
price REAL NOT NULL
)
`)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(
`INSERT INTO goods (title, price) VALUES (?, ?)`,
"pen", 2.0,
)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(
`INSERT INTO goods (title, price) VALUES (?, ?)`,
"book", 12.0,
)
if err != nil {
log.Fatal(err)
}
rows, err := db.Query(`SELECT id, title, price FROM goods`)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var id int
var title string
var price float64
err = rows.Scan(&id, &title, &price)
if err != nil {
log.Fatal(err)
}
fmt.Println(id, title, price)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
}
На экране две строки с идентификаторами,
названиями и ценами. Порядок столбцов
в Scan совпадает с порядком
в тексте SELECT.
Тот же прием для таблицы заказов:
package main
import (
"database/sql"
"fmt"
"log"
"os"
_ "modernc.org/sqlite"
)
func main() {
os.Remove("shop.db")
db, err := sql.Open("sqlite", "shop.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(`
CREATE TABLE orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
qty INTEGER NOT NULL,
price REAL NOT NULL
)
`)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(
`INSERT INTO orders (title, qty, price) VALUES (?, ?, ?)`,
"mug", 3, 9.5,
)
if err != nil {
log.Fatal(err)
}
rows, err := db.Query(
`SELECT id, title, qty, price FROM orders`,
)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var id, qty int
var title string
var price float64
err = rows.Scan(&id, &title, &qty, &price)
if err != nil {
log.Fatal(err)
}
fmt.Println(id, title, qty, price)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
}
Даны строки таблицы goods:
1 pen 2
2 book 12
Напишите цикл, который выведет только название каждой строки, если выборка уже открыта на все столбцы.
Скажите, зачем после цикла вызывают
проверку ошибки курсора, если на
каждом Scan ошибку уже смотрят.
Дан фрагмент без отложенного закрытия курсора. Скажите, какую строку нужно добавить и куда.