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

Внешний ключ в Go

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

В SQLite проверку включают командой PRAGMA foreign_keys = ON на открытом соединении. Без нее вставка с несуществующим номером может пройти тихо, и связь в данных развалится.

Создадим пользователей и заказы со ссылкой REFERENCES users (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 pack", ) if err != nil { log.Fatal(err) } fmt.Println("ok") }

На экране "ok". Номер 1 в 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 orders (user_id, title) VALUES (?, ?)`, 99, "ghost", ) if err != nil { fmt.Println("rejected") return } fmt.Println("saved") }

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

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 ('kim');

Включите проверку внешних ключей и добавьте заказ "box" для пользователя с номером 1. Выведите "done" при успехе.

Даны те же таблицы и включенная проверка. Попробуйте вставить заказ с user_id 50. При ошибке выведите "bad id".

Скажите, зачем команду PRAGMA foreign_keys = ON нужно выполнять на каждом новом открытии shop.db, а не один раз навсегда.

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