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

Левое соединение строк в Go

Внутреннее соединение отбрасывает строку слева, если справа не нашлось пары. Левое соединение оставляет строку слева, даже если справа пары нет: поля правой таблицы тогда приходят пустыми.

В Go такие столбцы читают в sql.NullString или sql.NullInt64 и смотрят флаг Valid перед использованием значения.

Выведем всех пользователей и их заказы, если они есть:

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) } rows, err := db.Query(` SELECT u.name, o.title FROM users u LEFT JOIN orders o ON o.user_id = u.id ORDER BY u.id, o.id `) if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { var userName string var orderTitle sql.NullString err = rows.Scan(&userName, &orderTitle) if err != nil { log.Fatal(err) } fmt.Println(userName) if orderTitle.Valid { fmt.Println(orderTitle.String) } else { fmt.Println("no order") } } err = rows.Err() if err != nil { log.Fatal(err) } }

Для числового столбца справа подойдет sql.NullInt64:

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, qty INTEGER NOT NULL, FOREIGN KEY (user_id) REFERENCES users (id) ) `) if err != nil { log.Fatal(err) } _, err = db.Exec(`INSERT INTO users (name) VALUES (?)`, "bob") if err != nil { log.Fatal(err) } rows, err := db.Query(` SELECT u.name, o.qty FROM users u LEFT JOIN orders o ON o.user_id = u.id WHERE u.name = ? `, "bob") if err != nil { log.Fatal(err) } defer rows.Close() if rows.Next() { var userName string var qty sql.NullInt64 err = rows.Scan(&userName, &qty) if err != nil { log.Fatal(err) } fmt.Println(userName) if qty.Valid { fmt.Println(qty.Int64) } else { fmt.Println("empty qty") } } err = rows.Err() if err != nil { log.Fatal(err) } }

Даны таблицы и строки:

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 (1, 'pen');

Составьте запрос от таблицы пользователей, чтобы в результате был "bob" с подписью "no order" вместо названия заказа. Прочитайте название в sql.NullString.

Даны таблицы teams и members с полем team_id. Одна команда без участников должна попасть в вывод с пустым именем участника. Опишите, какой тип в Scan взять для имени справа.

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

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