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

Соединение связанных таблиц в Rust

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

Условие совпадения пишут после слова ON. Для пары user и post обычно сравнивают post.user_id и user.id.

Выведем каждый пост вместе с именем автора:

use rusqlite::{Connection, params}; fn list_pairs() -> Result<(), rusqlite::Error> { let _ = std::fs::remove_file("app.db"); let conn = Connection::open("app.db")?; conn.execute("PRAGMA foreign_keys = ON", [])?; conn.execute( "CREATE TABLE user ( id INTEGER PRIMARY KEY, name TEXT NOT NULL )", [], )?; conn.execute( "CREATE TABLE post ( id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL, title TEXT NOT NULL, FOREIGN KEY (user_id) REFERENCES user(id) )", [], )?; conn.execute("INSERT INTO user (name) VALUES (?1)", params!["ann"])?; conn.execute( "INSERT INTO post (user_id, title) VALUES (?1, ?2)", params![1, "pen"], )?; conn.execute( "INSERT INTO post (user_id, title) VALUES (?1, ?2)", params![1, "book"], )?; let mut stmt = conn.prepare( "SELECT u.name, p.title FROM post p INNER JOIN user u ON p.user_id = u.id ORDER BY p.id", )?; let rows = stmt.query_map([], |row| { let name: String = row.get(0)?; let title: String = row.get(1)?; Ok((name, title)) })?; for item in rows { let (name, title) = item?; println!("{} {}", name, title); } Ok(()) } fn main() { match list_pairs() { Ok(()) => {} Err(e) => println!("{}", e), } }

Фильтр по имени пользователя ставят в WHERE уже после соединения:

use rusqlite::{Connection, params}; fn posts_by_name() -> Result<(), rusqlite::Error> { let _ = std::fs::remove_file("app.db"); let conn = Connection::open("app.db")?; conn.execute("PRAGMA foreign_keys = ON", [])?; conn.execute( "CREATE TABLE user ( id INTEGER PRIMARY KEY, name TEXT NOT NULL )", [], )?; conn.execute( "CREATE TABLE post ( id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL, title TEXT NOT NULL, FOREIGN KEY (user_id) REFERENCES user(id) )", [], )?; conn.execute("INSERT INTO user (name) VALUES (?1)", params!["ann"])?; conn.execute("INSERT INTO user (name) VALUES (?1)", params!["bob"])?; conn.execute( "INSERT INTO post (user_id, title) VALUES (?1, ?2)", params![1, "pen"], )?; conn.execute( "INSERT INTO post (user_id, title) VALUES (?1, ?2)", params![2, "lamp"], )?; let mut stmt = conn.prepare( "SELECT p.title FROM post p INNER JOIN user u ON p.user_id = u.id WHERE u.name = ?1", )?; let rows = stmt.query_map(params!["ann"], |row| { let title: String = row.get(0)?; Ok(title) })?; for item in rows { let title = item?; println!("{}", title); } Ok(()) } fn main() { match posts_by_name() { Ok(()) => {} Err(e) => println!("{}", e), } }

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

CREATE TABLE user ( id INTEGER PRIMARY KEY, name TEXT NOT NULL ); CREATE TABLE post ( id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL, title TEXT NOT NULL, FOREIGN KEY (user_id) REFERENCES user(id) ); INSERT INTO user (name) VALUES ('ann'); INSERT INTO post (user_id, title) VALUES (1, 'pen');

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

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

Даны те же user и post, что в примере с фильтром. Опишите словами, какие посты попадут в выборку, если в условии имя "bob".

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