Связь один ко многим в Rust
Связь один ко многим означает: одна строка родителя может иметь много дочерних, а каждая дочерняя указывает ровно на одного родителя. У одного пользователя может быть несколько постов, а у поста один пользователь.
В таблице post столбец user_id
повторяет один и тот же номер пользователя
для разных строк. Так видно, кому принадлежит
каждая запись, без копирования имени.
Добавим двух пользователей и три поста:
use rusqlite::{Connection, params};
fn seed() -> 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![1, "book"],
)?;
conn.execute(
"INSERT INTO post (user_id, title) VALUES (?1, ?2)",
params![2, "lamp"],
)?;
Ok(())
}
fn main() {
match seed() {
Ok(()) => println!("rows ready"),
Err(e) => println!("{}", e),
}
}
Число постов одного пользователя считают
фильтром по user_id:
use rusqlite::{Connection, params};
fn count_for_user() -> 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 total: i64 = conn.query_row(
"SELECT COUNT(*) FROM post WHERE user_id = ?1",
params![1],
|row| row.get(0),
)?;
println!("{}", total);
Ok(())
}
fn main() {
match count_for_user() {
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 user (name) VALUES ('bob');
INSERT INTO post (user_id, title) VALUES (2, 'cup');
Добавьте два поста для пользователя
"ann" и выведите число постов
с ее user_id.
Даны таблицы brand и model,
где у модели поле brand_id ссылается
на марку. Опишите столбцы обеих таблиц
для связи один ко многим.
В данных выше у пользователя "bob"
один пост. Скажите, сколько строк с
его user_id вернет счетчик
COUNT(*) без добавления новых записей.