Связь один ко многим в Go
Связь один ко многим означает: одна строка родителя может иметь много дочерних, а каждая дочерняя указывает ровно на одного родителя. У одного пользователя может быть несколько заказов, а у заказа один пользователь.
В таблице заказов столбец user_id
повторяет один и тот же номер пользователя
для разных строк. Так видно, кому принадлежит
каждая запись, без копирования имени.
Добавим двух пользователей и три заказа:
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.Exec("PRAGMA foreign_keys = ON")
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(`
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
)
`)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(`
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
title TEXT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users (id)
)
`)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(`INSERT INTO users (name) VALUES (?)`, "ann")
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(`INSERT INTO users (name) VALUES (?)`, "bob")
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(
`INSERT INTO orders (user_id, title) VALUES (?, ?)`,
1, "pen",
)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(
`INSERT INTO orders (user_id, title) VALUES (?, ?)`,
1, "book",
)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(
`INSERT INTO orders (user_id, title) VALUES (?, ?)`,
2, "lamp",
)
if err != nil {
log.Fatal(err)
}
fmt.Println("rows ready")
}
Число заказов одного пользователя считают
фильтром по user_id:
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.Exec("PRAGMA foreign_keys = ON")
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(`
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
)
`)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(`
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
title TEXT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users (id)
)
`)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(`INSERT INTO users (name) VALUES (?)`, "ann")
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(
`INSERT INTO orders (user_id, title) VALUES (?, ?)`,
1, "pen",
)
if err != nil {
log.Fatal(err)
}
_, err = db.Exec(
`INSERT INTO orders (user_id, title) VALUES (?, ?)`,
1, "book",
)
if err != nil {
log.Fatal(err)
}
var total int
err = db.QueryRow(
`SELECT COUNT(*) FROM orders WHERE user_id = ?`,
1,
).Scan(&total)
if err != nil {
log.Fatal(err)
}
fmt.Println(total)
}
Даны таблицы и строки:
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
title TEXT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users (id)
);
INSERT INTO users (name) VALUES ('ann');
INSERT INTO users (name) VALUES ('bob');
INSERT INTO orders (user_id, title) VALUES (2, 'cup');
Добавьте два заказа для пользователя
"ann" и выведите число заказов
с ее user_id.
Даны таблицы brands и models,
где у модели поле brand_id ссылается
на марку. Опишите столбцы обеих таблиц
для связи один ко многим.
В данных выше у пользователя "bob"
один заказ. Скажите, сколько строк с
его user_id вернет счетчик
COUNT(*) без добавления новых записей.