Следите за новинками
в нашем Telegram канале. Жми, чтобы подписаться:)
⊗goSpRlCh 225 of 280 menu
◀ ▶

Цепочка из трех таблиц в Go

Иногда нужны поля из трех таблиц подряд: заказ ссылается на пользователя и на товар, а отдельного столбца от пользователя к товару не требуется. Достаточно двух связей в цепочке.

Цепочка соединяет три таблицы двумя шагами: сначала заказы к пользователям, затем заказы к товарам. Каждый шаг сравнивает номера в условии ON.

Подготовим данные и выведем имя, заказ и название товара:

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 goods ( id INTEGER PRIMARY KEY, title TEXT NOT NULL ) `) if err != nil { log.Fatal(err) } _, err = db.Exec(` CREATE TABLE orders ( id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL, good_id INTEGER NOT NULL, FOREIGN KEY (user_id) REFERENCES users (id), FOREIGN KEY (good_id) REFERENCES goods (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 goods (title) VALUES (?)`, "pen") if err != nil { log.Fatal(err) } _, err = db.Exec( `INSERT INTO orders (user_id, good_id) VALUES (?, ?)`, 1, 1, ) if err != nil { log.Fatal(err) } rows, err := db.Query(` SELECT u.name, o.id, g.title FROM orders o INNER JOIN users u ON o.user_id = u.id INNER JOIN goods g ON o.good_id = g.id ORDER BY o.id `) if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { var userName string var orderID int var goodTitle string err = rows.Scan(&userName, &orderID, &goodTitle) if err != nil { log.Fatal(err) } fmt.Println(userName, orderID, goodTitle) } err = rows.Err() if err != nil { log.Fatal(err) } }

Фильтр по имени пользователя ставят после обоих шагов цепочки:

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 goods ( id INTEGER PRIMARY KEY, title TEXT NOT NULL ) `) if err != nil { log.Fatal(err) } _, err = db.Exec(` CREATE TABLE orders ( id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL, good_id INTEGER NOT NULL, FOREIGN KEY (user_id) REFERENCES users (id), FOREIGN KEY (good_id) REFERENCES goods (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 goods (title) VALUES (?)`, "pen") if err != nil { log.Fatal(err) } _, err = db.Exec(`INSERT INTO goods (title) VALUES (?)`, "book") if err != nil { log.Fatal(err) } _, err = db.Exec( `INSERT INTO orders (user_id, good_id) VALUES (?, ?)`, 1, 1, ) if err != nil { log.Fatal(err) } _, err = db.Exec( `INSERT INTO orders (user_id, good_id) VALUES (?, ?)`, 2, 2, ) if err != nil { log.Fatal(err) } rows, err := db.Query(` SELECT g.title FROM orders o INNER JOIN users u ON o.user_id = u.id INNER JOIN goods g ON o.good_id = g.id WHERE u.name = ? `, "ann") if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { var goodTitle string err = rows.Scan(&goodTitle) if err != nil { log.Fatal(err) } fmt.Println(goodTitle) } err = rows.Err() if err != nil { log.Fatal(err) } }

Даны таблицы:

CREATE TABLE users ( id INTEGER PRIMARY KEY, name TEXT NOT NULL ); CREATE TABLE goods ( id INTEGER PRIMARY KEY, title TEXT NOT NULL ); CREATE TABLE orders ( id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL, good_id INTEGER NOT NULL, FOREIGN KEY (user_id) REFERENCES users (id), FOREIGN KEY (good_id) REFERENCES goods (id) );

Товар лежит в подкатегории, подкатегория в категории. Опишите три таблицы и столбцы ссылок без текста запроса выборки.

Даны users, orders и goods как в примере урока. Напишите запрос, который выведет имя пользователя, номер заказа и название товара для каждой строки заказа.

Скажите, сколько шагов соединения нужно, чтобы из orders получить и имя пользователя, и название товара.

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить