Одна строка выборки в Go
Когда нужна ровно одна строка, используют
отдельную команду выборки одной строки.
Она сразу читает столбцы в переменные
без Next и без ручного закрытия
курсора в типичном случае.
Если под условие ничего не подошло,
приходит особая ошибка sql.ErrNoRows.
Ее сравнивают через пакет errors
и отличают от сбоя связи или синтаксиса.
Найдем цену товара по идентификатору:
package main
import (
"database/sql"
"errors"
"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)
}
var price float64
err = db.QueryRow(
`SELECT price FROM goods WHERE id = ?`,
1,
).Scan(&price)
if err != nil {
log.Fatal(err)
}
fmt.Println(price)
}
На экране 2. Одной команды хватило,
чтобы получить одно число из столбца
price.
Проверим отсутствие строки по другому идентификатору:
package main
import (
"database/sql"
"errors"
"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)
}
var title string
err = db.QueryRow(
`SELECT title FROM goods WHERE id = ?`,
99,
).Scan(&title)
if errors.Is(err, sql.ErrNoRows) {
fmt.Println("not found")
return
}
if err != nil {
log.Fatal(err)
}
fmt.Println(title)
}
Дана таблица:
goods: id=2 title="book" price=12
Опишите, как прочитать title
для id равного 2 одной
командой без цикла.
После чтения одной строки вернулась
ошибка sql.ErrNoRows. Скажите,
означает ли это, что таблица повреждена.
Скажите, когда уместнее цикл по курсору, а когда чтение одной строки.