CRUD操作
クエリと実行
「CRUD操作」はCoddyKit上の無料Learn Rust Codingレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLearn Rust Coding学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Learn Rust Codingコースには全4レッスンが含まれています。
sqlxによるCRUD
CRUDはCreate、Read、Update、Deleteを意味します。sqlxでは、これらを2種類の実行方法に分けています。
- 行を返すクエリには
fetch_* - データを変更する文には
execute
Create(INSERT)
バインドパラメーターを使って行を挿入し、executeで実行します。生成されたIDを取得するにはRETURNINGを使います。
use sqlx::{Pool, Postgres};
async fn create(pool: &Pool<Postgres>, name: &str) -> i32 {
let rec = sqlx::query!(
"INSERT INTO users (name) VALUES ($1) RETURNING id",
name
).fetch_one(pool).await.unwrap();
rec.id
}1行を読み取る
fetch_oneは行がちょうど1つ返ることを想定し、それ以外の場合はエラーになります。行が存在しない可能性がある場合はfetch_optionalを使います。
use sqlx::{Pool, Postgres};
async fn find(pool: &Pool<Postgres>, id: i32) -> Option<String> {
let rec = sqlx::query!("SELECT name FROM users WHERE id = $1", id)
.fetch_optional(pool)
.await
.unwrap();
rec.map(|r| r.name)
}複数行を読み取る
fetch_allは、条件に一致するすべての行をVecとして返します。
use sqlx::{Pool, Postgres};
async fn all_names(pool: &Pool<Postgres>) -> Vec<String> {
let rows = sqlx::query!("SELECT name FROM users ORDER BY id")
.fetch_all(pool)
.await
.unwrap();
rows.into_iter().map(|r| r.name).collect()
}Update
UPDATE文ではexecuteを使います。executeは、影響を受けた行数を含む結果を返します。
use sqlx::{Pool, Postgres};
async fn rename(pool: &Pool<Postgres>, id: i32, name: &str) -> u64 {
let res = sqlx::query!("UPDATE users SET name = $1 WHERE id = $2", name, id)
.execute(pool)
.await
.unwrap();
res.rows_affected()
}Delete
DELETEでもexecuteを使います。rows_affected()を確認すると、実際に削除されたかどうかが分かります。
use sqlx::{Pool, Postgres};
async fn delete(pool: &Pool<Postgres>, id: i32) -> bool {
let res = sqlx::query!("DELETE FROM users WHERE id = $1", id)
.execute(pool)
.await
.unwrap();
res.rows_affected() > 0
}RustだけでCRUDをモデル化する
メモリ上のマップに対するCRUDは、sqlxがテーブルに対して行う同じ操作を再現します。
use std::collections::HashMap;
fn main() {
let mut users: HashMap<i32, String> = HashMap::new();
users.insert(1, "Alice".to_string()); // create
println!("{:?}", users.get(&1)); // read
users.insert(1, "Alicia".to_string()); // update
println!("{:?}", users.get(&1));
users.remove(&1); // delete
println!("{:?}", users.get(&1));
}トランザクション
トランザクションを使うと、複数の文をアトミックにまとめられます。commitですべて成功するか、どれも適用されないかのどちらかになります。
use sqlx::{Pool, Postgres};
async fn transfer(pool: &Pool<Postgres>) {
let mut tx = pool.begin().await.unwrap();
sqlx::query!("UPDATE acct SET bal = bal - 10 WHERE id = 1")
.execute(&mut *tx).await.unwrap();
sqlx::query!("UPDATE acct SET bal = bal + 10 WHERE id = 2")
.execute(&mut *tx).await.unwrap();
tx.commit().await.unwrap();
}ロールバック
トランザクションガードがcommitなしで破棄されると、sqlxは自動的にロールバックします。rollbackを明示的に呼び出すこともできます。
use sqlx::{Pool, Postgres};
async fn maybe(pool: &Pool<Postgres>, ok: bool) {
let mut tx = pool.begin().await.unwrap();
sqlx::query!("INSERT INTO log (msg) VALUES ('x')").execute(&mut *tx).await.unwrap();
if ok { tx.commit().await.unwrap(); } else { tx.rollback().await.unwrap(); }
}大量の読み取りをストリーミングする
非常に大きな結果セットでは、fetchがストリームを返します。すべてをメモリに読み込まずに行を処理できます。
use sqlx::{Pool, Postgres};
use futures::TryStreamExt;
async fn stream(pool: &Pool<Postgres>) {
let mut rows = sqlx::query!("SELECT id FROM big_table").fetch(pool);
while let Some(row) = rows.try_next().await.unwrap() {
println!("id {}", row.id);
}
}エラー処理
データベース呼び出しはResultを返します。Result<_, sqlx::Error>を返す関数では、アンラップする代わりに?でエラーを伝播させます。
use sqlx::{Pool, Postgres};
async fn count(pool: &Pool<Postgres>) -> Result<i64, sqlx::Error> {
let rec = sqlx::query!("SELECT COUNT(*) as n FROM users")
.fetch_one(pool)
.await?;
Ok(rec.n.unwrap_or(0))
}理解度チェック
CRUD操作についての理解度を確認しましょう。
まとめ
sqlxによるCRUDについて学びました。
fetch_one、fetch_optional、fetch_allで行を読み取りますexecuteでデータを変更し、rows_affected()で影響を受けた行数を確認しますRETURNINGで生成された値を取得しますbegin/commit/rollbackによるトランザクションでアトミック性を保証します
次は、スキーマを発展させるマイグレーションです。
よくある質問
「CRUD操作」レッスンは無料ですか?
はい。「CRUD操作」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Learn Rust Codingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Learn Rust Codingコースには全4レッスンが含まれています。
「CRUD操作」で何を学びますか?
クエリと実行 ブラウザで直接実行するハンズオンコードでLearn Rust Codingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Learn Rust Codingを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのLearn Rust Codingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「CRUD操作」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このLearn Rust Codingレッスンでコードを書いて実行できますか?
はい。すべてのLearn Rust Codingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。