サンプル集  >  Rust  >  MySQLのデータ検索(SQLx)
MySQLのデータ検索(SQLx)
2025/12/06

RustでSQLxクレートを使ってMySQLのデータを検索してみます。

  1. プロジェクトの作成
  2. プログラム作成
◆環境
OS Windows 11 Home 25H2
rustc 1.91.1
cargo 1.91.1

プロジェクトの作成

プロジェクトを作成します。

cargo new sqlxtest

コマンドプロンプトでプロジェクトを作成したいフォルダへ移動しコマンドを実行します。

cargo new sqlxtest
    Creating binary (application) `sqlxtest` package
warning: compiling this new package may not work due to invalid works
pace configuration

failed to parse manifest at `C:\src\Cargo.toml`

Caused by:
  no targets specified in the manifest
  either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section
 must be present
note: see more `Cargo.toml` keys and their definitions at https://doc
.rust-lang.org/cargo/reference/manifest.html

プログラム作成

ポイントは以下になります。

  1. コネクションプールを使う。(MySqlPoolOptions::new())
  2. プリペアドステートメントを使う。(?とbind())
  3. 接続文字列はハードコーディングせず.envで管理する。

Cargo.toml
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
[package]
name = "sqlxtest"
version = "0.1.0"
edition = "2024"

[dependencies]
sqlx = { version = "0.7", features = ["mysql"
                                    , "runtime-tokio"
                                    , "macros"
                                    , "rust_decimal"
                                    , "chrono"
                                    ] }
tokio = { version = "1", features = ["full"] }
dotenvy = "0.15"
rust_decimal = "1"
anyhow = "1"
chrono = "0.4"

main.rs
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
66: 
67: 
68: 
69: 
70: 
71: 
72: 
73: 
use sqlx::mysql::{MySqlPool, MySqlPoolOptions};
use anyhow::Result;
use rust_decimal::Decimal;
use chrono::NaiveDateTime;
use std::{thread, time};

#[derive(Debug, sqlx::FromRow)]
struct Rec {
    id: i64,
    rec_date: NaiveDateTime,
    rec_value: Option<Decimal>,
}

async fn get_rec(pool: &MySqlPool, id: i64) -> Result<Rec> {

    let rec = sqlx::query_as::<_, Rec>(
        "SELECT * FROM rec_values WHERE id=?"
    )
    .bind(id)
    .fetch_optional(pool)
    .await?
    .ok_or_else(|| anyhow::anyhow!("id not found: {}", id))?;

    Ok(rec)
}

#[tokio::main]
async fn main() -> Result<()> {
    println!("Hello, world!");
    dotenvy::dotenv().ok();

    let database_user = std::env::var("DATABASE_USER")?;
    let database_pass = std::env::var("DATABASE_PASS")?;
    let database_host = std::env::var("DATABASE_HOST")?;
    let database_port = std::env::var("DATABASE_PORT")?;
    let database_db   = std::env::var("DATABASE_DB")?;

    let connection_string
    = format!("mysql://{}:{}@{}:{}/{}"
            , database_user
            , database_pass
            , database_host
            , database_port
            , database_db
            );
    println!("{}",connection_string);

    let pool = MySqlPoolOptions::new()
        .max_connections(10)
        .connect(&connection_string)
        .await?;

    let id = 1;
    let rec = get_rec(&pool, id).await?;

    // rec_value は Option なので match で表示
    match rec.rec_value {
        Some(v) => println!("id={} date={} value={}"
                          , rec.id
                          , rec.rec_date
                          , v
                          ),
        None    => println!("id={} date={} value=NULL"
                          , rec.id
                          , rec.rec_date
                          ),
    }

    // 接続数確認のため5秒スリープ
    thread::sleep(time::Duration::from_secs(5));

    Ok(())
}

DBはDocker上に構築していてlocalhost:13306で待ち受けているのでポートは13306にしました。

docker container restart mysql-container-8.0.41

.env
1: 
2: 
3: 
4: 
5: 
DATABASE_USER=root
DATABASE_PASS=root
DATABASE_HOST=localhost
DATABASE_PORT=13306
DATABASE_DB=MyDB

テーブルとテストデータを作成します。

sql-rec_values.txt
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
CREATE TABLE IF NOT EXISTS rec_values (
  id INT PRIMARY KEY AUTO_INCREMENT,
  rec_date
    DATETIME NOT NULL
    DEFAULT CURRENT_TIMESTAMP
         ON UPDATE CURRENT_TIMESTAMP,
  rec_value DECIMAL(3, 1)
);

INSERT INTO rec_values (rec_value) VALUES (12.3);

実行してみます。

PS C:\src\sqlxtest> cargo run
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.2
5s
     Running `target\debug\sqlxtest.exe`
Hello, world!
mysql://root:root@localhost:13306/MyDB
id=1 date=2026-03-15 09:22:16 value=12.3

MySQLで接続数を確認したところ実行中は1増えていました。

mysql> SHOW STATUS LIKE 'Threads_connected';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_connected | 2     |
+-------------------+-------+
1 row in set (0.00 sec)

期待通りに動作しました。

関連項目

Docker MySQL
MySQLでテーブル作成、データ追加、検索
MySQLのデータ検索(SQLx)②
MySQLのデータ追加(SQLx)

▲ PageTop  ■ Home


Copyright (C) 2026 ymlib.com