データベース

SQLx-cliのインストールと基本的な使い方ガイド

目次

RustでSQLxを使って効率的にデータベース操作を行う方法

Rustでデータベース操作を効率的に行うために、SQLxという非同期対応のクレートが非常に有用です。
SQLxは、コンパイル時にSQLクエリを検証するため、安全でエラーが少ないコードを作成するのに役立ちます。

use sqlx::{Pool, postgres::PgPoolOptions};

#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
    let pool = PgPoolOptions::new()
        .max_connections(5)
        .connect("postgres://user:password@localhost/database").await?;

    let row: (i32,) = sqlx::query_as("SELECT 1")
        .fetch_one(&pool).await?;
    
    println!("Query result: {}", row.0);
    Ok(())
}

上記のコードは、RustでPostgreSQLデータベースに接続し、簡単なクエリを実行する例です。
非同期の`main`関数内でSQLxの機能を使い、接続プールを作成し、クエリを実行しています。

SQLxの概要と利点

SQLxは、Rustのための非同期対応のデータベースライブラリであり、主要な利点は以下の通りです:
– コンパイル時のSQLクエリの検証により、ランタイムエラーの削減。

– 非同期操作のサポートにより、高いスループットを実現。

– 複数のデータベースバックエンド(PostgreSQL、MySQL、SQLite)をサポート。

これらの特徴により、SQLxは安全かつ効率的にデータベース操作を行うための強力なツールとなります。

SQLxのインストールとセットアップ

SQLxをプロジェクトに追加するには、`Cargo.toml`ファイルに以下の依存関係を追加します:

[dependencies]
sqlx = { version = "0.5", features = ["runtime-tokio", "postgres"] }
tokio = { version = "1", features = ["full"] }

次に、Rustプロジェクトのメインファイルに以下を追加して、SQLxの機能をインポートします:

use sqlx::{Pool, postgres::PgPoolOptions};

この設定により、SQLxを使用してデータベース接続やクエリ実行が可能になります。

基本的なクエリの実行方法

基本的なクエリの実行には、`query!`や`query_as!`マクロを使用します。
以下は、データベースからレコードを取得する簡単な例です:

let row: (i32,) = sqlx::query_as("SELECT id FROM users WHERE username = 'user1'")
    .fetch_one(&pool).await?;

このコードは、ユーザー名が”user1″であるユーザーのIDを取得します。
`fetch_one`は単一の結果を返し、結果がない場合や複数の結果がある場合はエラーをスローします。

トランザクションの管理方法

トランザクションを使用することで、一連の操作が全て成功するか、全て失敗するかを保証します。
SQLxでは以下のようにトランザクションを管理します:

let mut tx = pool.begin().await?;
sqlx::query("INSERT INTO users (username) VALUES ('user2')")
    .execute(&mut tx).await?;
tx.commit().await?;

このコードは、新しいユーザーを挿入するトランザクションを開始し、成功した場合にコミットします。
エラーが発生した場合はロールバックされます。

非同期操作の活用

非同期操作を活用することで、スケーラブルなアプリケーションを構築できます。
SQLxは非同期APIを提供しており、`await`を使用して非同期操作を簡単に行えます。
例えば、複数のクエリを並列に実行することができます:

let user1 = sqlx::query_as!(User, "SELECT * FROM users WHERE id = 1").fetch_one(&pool);
let user2 = sqlx::query_as!(User, "SELECT * FROM users WHERE id = 2").fetch_one(&pool);

let (user1, user2) = tokio::try_join!(user1, user2)?;

これにより、両方のクエリが同時に実行され、全体の待ち時間が短縮されます。

SQLx::sqliteを使用したSQLiteデータベースの操作方法

SQLiteは軽量で組み込み向けのデータベースとして広く使用されています。
SQLx::sqliteを使用することで、Rustから効率的にSQLiteデータベースを操作することが可能です。
以下に、基本的なセットアップとクエリの実行方法を紹介します。

use sqlx::sqlite::SqlitePoolOptions;

#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
    let pool = SqlitePoolOptions::new()
        .max_connections(5)
        .connect("sqlite::memory:").await?;

    sqlx::query("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)")
        .execute(&pool).await?;
    
    sqlx::query("INSERT INTO users (name) VALUES ('Alice')")
        .execute(&pool).await?;
    
    let row: (i32, String) = sqlx::query_as("SELECT id, name FROM users WHERE name = 'Alice'")
        .fetch_one(&pool).await?;
    
    println!("User: {} - {}", row.0, row.1);
    Ok(())
}

上記のコードは、SQLiteデータベースをメモリ内で作成し、テーブルを作成し、データを挿入し、クエリを実行する例です。

SQLiteとSQLx::sqliteの基本概念

SQLiteは、サーバーレスで自己完結型のデータベースエンジンです。
SQLx::sqliteを使用することで、Rustアプリケーションから簡単にSQLiteデータベースにアクセスできます。
SQLx::sqliteは、他のSQLxバックエンドと同様に、非同期操作とコンパイル時のクエリ検証をサポートしています。

SQLiteデータベースの接続方法

SQLiteデータベースへの接続は非常に簡単です。
以下のコードは、SQLiteデータベースへの接続を示しています:

let pool = SqlitePoolOptions::new()
    .max_connections(5)
    .connect("sqlite::memory:").await?;

この例では、メモリ内データベースを使用していますが、ファイルベースのデータベースを使用することも可能です。

SQLx::sqliteを使ったCRUD操作

CRUD操作(作成、読み取り、更新、削除)は、データベース操作の基本です。
以下の例は、ユーザーの追加、読み取り、更新、削除を行います:

sqlx::query("INSERT INTO users (name) VALUES ('Bob')")
    .execute(&pool).await?;

let row: (i32, String) = sqlx::query_as("SELECT id, name FROM users WHERE name = 'Bob'")
    .fetch_one(&pool).await?;

sqlx::query("UPDATE users SET name = 'Robert' WHERE id = ?")
    .bind(row.0)
    .execute(&pool).await?;

sqlx::query("DELETE FROM users WHERE id = ?")
    .bind(row.0)
    .execute(&pool).await?;

エラーハンドリングとデバッグ

データベース操作中にエラーが発生した場合、適切なエラーハンドリングが重要です。
SQLxは詳細なエラーメッセージを提供するため、デバッグが容易です。
以下は、エラーをキャッチして処理する例です:

if let Err(e) = sqlx::query("INSERT INTO users (name) VALUES (NULL)").execute(&pool).await {
    eprintln!("Error occurred: {}", e);
}

パフォーマンス最適化のポイント

SQLiteデータベースのパフォーマンスを最適化するためのポイントは以下の通りです:
– 適切なインデックスの使用
– トランザクションの活用
– クエリの最適化

これにより、SQLiteデータベースを効率的に操作することが可能です。

GolangでSQLxを利用してデータベースを効率的に操作する方法

GolangでSQLxを利用すると、データベース操作が非常に簡単かつ効率的になります。
SQLxは、構造体とデータベースの行をマッピングするための機能を提供し、クエリの実行を簡素化します。

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
    "github.com/jmoiron/sqlx"
)

type User struct {
    ID   int    `db:"id"`
    Name string `db:"name"`
}

func main() {
    db, err := sqlx.Connect("postgres", "user=postgres password=mysecretpassword dbname=mydb sslmode=disable")
    if err != nil {
        fmt.Println(err)
        return
    }

    var user User
    err = db.Get(&user, "SELECT id, name FROM users WHERE name=$1", "Alice")
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Printf("User: %d, %s\n", user.ID, user.Name)
}

上記のコードは、GolangでPostgreSQLデータベースに接続し、ユーザー情報を取得する例です。

SQLxのインストールと基本設定

GolangでSQLxを使用するには、まず以下のコマンドでSQLxをインストールします:

go get github.com/jmoiron/sqlx

次に、`sqlx`パッケージをインポートし、データベース接続を設定します:

import (
    "github.com/jmoiron/sqlx"
    _ "github.com/lib/pq"
)

データベース接続と基本的なクエリ実行

SQLxを使ってデータベースに接続する方法は以下の通りです:

db, err := sqlx.Connect("postgres", "user=postgres password=mysecretpassword dbname=mydb sslmode=disable")
if err != nil {
    log.Fatalln(err)
}

基本的なクエリの実行は、`Get`や`Select`メソッドを使用します:

var user User
err = db.Get(&user, "SELECT id, name FROM users WHERE name=$1", "Alice")
if err != nil {
    log.Fatalln(err)
}

構造体とSQLxのマッピング

SQLxは、データベースの行をGoの構造体に自動的にマッピングするため、コードが簡潔になります。
以下のように構造体を定義します:

type User struct {
    ID   int    `db:"id"`
    Name string `db:"name"`
}

クエリ結果を構造体にマッピングするには、`Get`や`Select`メソッドを使用します:

var users []User
err := db.Select(&users, "SELECT id, name FROM users")
if err != nil {
    log.Fatalln(err)
}

トランザクションの利用と管理

トランザクションを使用することで、一連の操作が全て成功するか、全て失敗するかを保証します。
以下は、トランザクションの例です:

tx := db.MustBegin()
tx.MustExec("INSERT INTO users (name) VALUES ($1)", "Bob")
tx.MustExec("INSERT INTO users (name) VALUES ($1)", "Charlie")
err := tx.Commit()
if err != nil {
    tx.Rollback()
    log.Fatalln(err)
}

SQLxの高度な機能とベストプラクティス

SQLxは、カスタムマッパーやスキャンフック、複雑なクエリのサポートなど、高度な機能を提供します。
ベストプラクティスとしては、以下を考慮します:
– プリペアドステートメントの活用
– 適切なエラーハンドリング
– パフォーマンスのためのクエリ最適化

これにより、Golangアプリケーションのデータベース操作を効率的に行うことができます。

SQLx-cliのインストールと基本的な使い方ガイド

SQLx-cliは、SQLxを利用するプロジェクトのためのコマンドラインインターフェースであり、SQLスキーマの生成やデータベース操作を効率的に行うことができます。
このガイドでは、SQLx-cliのインストール方法と基本的な使い方について説明します。

SQLx-cliとは?その利便性について

SQLx-cliは、RustプロジェクトでSQLxを利用するための補助ツールです。
主な利便性は以下の通りです:
– SQLスキーマのマイグレーション管理
– クエリのプリパレーションとテスト
– データベース接続の管理とデバッグ

これにより、開発者はデータベース操作を簡単かつ効率的に行うことができます。

SQLx-cliのインストール手順

SQLx-cliをインストールするには、以下のコマンドを使用します:

cargo install sqlx-cli --no-default-features --features postgres

このコマンドは、PostgreSQL用のSQLx-cliをインストールします。
他のデータベースを使用する場合は、`–features`オプションを変更してください。

基本的なコマンドの使い方

SQLx-cliの基本的なコマンドには以下があります:
– `sqlx db create`:データベースの作成
– `sqlx db drop`:データベースの削除
– `sqlx migrate run`:マイグレーションの実行

以下に、マイグレーションを実行する例を示します:

sqlx migrate add create_users_table

このコマンドは、新しいマイグレーションファイルを作成します。
次に、SQLスクリプトを編集し、以下のようにテーブルを作成します:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

その後、マイグレーションを実行します:

sqlx migrate run

SQLスキーマの生成と管理

SQLx-cliを使用すると、SQLスキーマを自動生成し、管理することができます。
例えば、以下のコマンドでスキーマを生成します:

sqlx db generate-schema

このコマンドは、データベースの現在のスキーマを検査し、Rust構造体を自動生成します。

トラブルシューティングとよくある問題の解決法

SQLx-cliを使用する際に発生する一般的な問題には以下のようなものがあります:
– データベース接続エラー:接続文字列が正しいか確認してください。

– マイグレーションエラー:SQLスクリプトの文法を確認し、エラーメッセージに従って修正してください。

トラブルシューティングのための有用なコマンドは以下の通りです:

sqlx db reset
sqlx db migrate info

これらのコマンドを使用して、データベースの状態を確認し、問題を解決します。

SQLcとSQLxを併用した効率的なクエリ生成と実行

SQLcは、SQLクエリを静的に解析し、対応する型安全なコードを生成するツールです。
SQLxと組み合わせて使用することで、クエリの生成と実行が効率的かつ安全になります。

SQLcの概要とSQLxとの連携方法

SQLcは、SQLファイルからRustコードを生成し、SQLxと連携することで、データベースクエリを型安全に実行することができます。
SQLcの利点は以下の通りです:
– 型安全なクエリ生成
– コンパイル時のクエリ検証
– クエリの再利用性向上

SQLcを使ったクエリの自動生成

SQLcを使用するには、SQLファイルを準備し、以下のコマンドを実行します:

sqlc generate

例えば、以下のようなSQLファイルを作成します:

-- name: GetUser :one
SELECT id, name FROM users WHERE id = $1;

このファイルに基づいて、SQLcは対応するRustコードを生成します。

SQLxによる生成されたクエリの実行

生成されたRustコードを使用して、SQLxでクエリを実行します。
以下は、SQLcで生成されたクエリをSQLxで実行する例です:

let user = sqlx::query_as!(User, "SELECT id, name FROM users WHERE id = $1", user_id)
    .fetch_one(&pool).await?;

このコードは、SQLcで生成されたクエリを使用して、指定されたユーザーIDのユーザー情報を取得します。

SQLcとSQLxのベストプラクティス

SQLcとSQLxを併用する際のベストプラクティスは以下の通りです:
– クエリを明確に分離し、再利用性を高める
– コンパイル時にクエリを検証し、ランタイムエラーを防ぐ
– 適切なエラーハンドリングを実装する

これにより、安全で効率的なデータベース操作が可能になります。

複雑なクエリの生成と管理

複雑なクエリもSQLcとSQLxを使用して管理することができます。
以下は、複数のテーブルを結合する複雑なクエリの例です:

-- name: GetUserWithPosts :many
SELECT users.id, users.name, posts.id AS post_id, posts.title
FROM users
JOIN posts ON users.id = posts.user_id
WHERE users.id = $1;

このクエリをSQLcで生成し、SQLxで実行します:

let results = sqlx::query_as!(UserWithPosts, "SELECT users.id, users.name, posts.id AS post_id, posts.title FROM users JOIN posts ON users.id = posts.user_id WHERE users.id = $1", user_id)
    .fetch_all(&pool).await?;

このコードは、指定されたユーザーとその投稿を取得します。

RustでSQLxを使用してINSERT文を実行する方法とベストプラクティス

Rustでデータベースにデータを挿入する際、SQLxを使うと安全かつ効率的にINSERT文を実行できます。
SQLxは、非同期操作をサポートし、コンパイル時にクエリを検証するため、エラーを未然に防ぐことができます。

use sqlx::postgres::PgPoolOptions;

#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
    let pool = PgPoolOptions::new()
        .max_connections(5)
        .connect("postgres://user:password@localhost/database").await?;

    let result = sqlx::query!(
        "INSERT INTO users (name, email) VALUES ($1, $2)",
        "Alice",
        "alice@example.com"
    )
    .execute(&pool).await?;

    println!("Inserted row ID: {}", result.last_insert_id());
    Ok(())
}

上記のコードは、PostgreSQLデータベースにユーザー情報を挿入する例です。
`sqlx::query!`マクロを使用して、SQLクエリをコンパイル時に検証し、非同期で実行しています。

INSERT文の基本と準備

INSERT文は、データベースに新しいデータを追加するために使用されます。
RustでSQLxを使用する場合、まずデータベース接続を確立し、INSERT文を準備します。
以下のコードは、基本的なINSERT文の例です:

sqlx::query!(
    "INSERT INTO users (name, email) VALUES ($1, $2)",
    "Alice",
    "alice@example.com"
)
.execute(&pool).await?;

このクエリは、ユーザー名とメールアドレスを持つ新しいユーザーを追加します。

SQLxを使った基本的なINSERT文の実行

SQLxを使ったINSERT文の実行は、非常に簡単です。
以下のコードは、ユーザー情報を挿入する方法を示しています:

let result = sqlx::query!(
    "INSERT INTO users (name, email) VALUES ($1, $2)",
    "Bob",
    "bob@example.com"
)
.execute(&pool).await?;

println!("Inserted row ID: {}", result.last_insert_id());

このコードは、新しいユーザーをデータベースに追加し、挿入された行のIDを出力します。

トランザクションを使ったINSERT文の管理

トランザクションを使用すると、複数のINSERT操作を一つの論理的な単位としてまとめることができます。
これにより、一連の操作が全て成功するか、全て失敗するかを保証します。
以下は、トランザクションを使用した例です:

let mut tx = pool.begin().await?;
sqlx::query!("INSERT INTO users (name, email) VALUES ($1, $2)", "Charlie", "charlie@example.com")
    .execute(&mut tx).await?;
sqlx::query!("INSERT INTO orders (user_id, item) VALUES ($1, $2)", 1, "Item1")
    .execute(&mut tx).await?;
tx.commit().await?;

このコードは、ユーザー情報と注文情報をトランザクション内で挿入し、全ての操作が成功した場合にコミットします。

エラーハンドリングとデバッグ方法

INSERT操作中にエラーが発生した場合、適切なエラーハンドリングが必要です。
SQLxは詳細なエラーメッセージを提供するため、デバッグが容易です。
以下は、エラーをキャッチして処理する例です:

if let Err(e) = sqlx::query!("INSERT INTO users (name, email) VALUES ($1, $2)", "Dave", "dave@example.com")
    .execute(&pool).await {
    eprintln!("Error occurred: {}", e);
}

このコードは、INSERT操作中に発生したエラーをキャッチし、エラーメッセージを出力します。

効率的なINSERT文の書き方と最適化

INSERT文を効率的に書くためのポイントは以下の通りです:
– バッチINSERTを使用して、複数の行を一度に挿入する
– プレースホルダーを使用してSQLインジェクションを防ぐ
– トランザクションを活用して一連の操作をまとめる

以下は、バッチINSERTの例です:

let users = vec![
    ("Eve", "eve@example.com"),
    ("Frank", "frank@example.com")
];

for user in users {
    sqlx::query!("INSERT INTO users (name, email) VALUES ($1, $2)", user.0, user.1)
        .execute(&pool).await?;
}

このコードは、複数のユーザーを一度に挿入し、パフォーマンスを向上させます。

RustでSQLx::postgresを使ってPostgreSQLを操作する方法

RustでSQLx::postgresを使うと、PostgreSQLデータベースを効率的に操作できます。
SQLx::postgresは、非同期操作をサポートし、コンパイル時にクエリを検証するため、安全で効率的なデータベース操作が可能です。

use sqlx::postgres::PgPoolOptions;

#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
    let pool = PgPoolOptions::new()
        .max_connections(5)
        .connect("postgres://user:password@localhost/database").await?;

    let row: (i32, String) = sqlx::query_as!("SELECT id, name FROM users WHERE id = $1", 1)
        .fetch_one(&pool).await?;
    
    println!("User ID: {}, Name: {}", row.0, row.1);
    Ok(())
}

上記のコードは、RustでPostgreSQLデータベースに接続し、ユーザー情報を取得する例です。

SQLx::postgresの概要と基本設定

SQLx::postgresは、PostgreSQLデータベースとやり取りするためのRustクレートです。
非同期操作をサポートし、コンパイル時にクエリを検証するため、安全で効率的です。
以下のコードは、SQLx::postgresの基本設定です:

[dependencies]
sqlx = { version = "0.5", features = ["runtime-tokio", "postgres"] }
tokio = { version = "1", features = ["full"] }

この設定により、SQLx::postgresとTokioランタイムをプロジェクトに追加します。

PostgreSQLデータベースへの接続

PostgreSQLデータベースへの接続は非常に簡単です。
以下のコードは、PostgreSQLデータベースに接続する方法を示しています:

let pool = PgPoolOptions::new()
    .max_connections(5)
    .connect("postgres://user:password@localhost/database").await?;

このコードは、最大5つの接続を持つ接続プールを作成します。

SQLx::postgresを使ったクエリ実行

SQLx::postgresを使ったクエリ実行は、非常に簡単です。
以下のコードは、ユーザー情報を取得する方法を示しています:

let row: (i32, String) = sqlx::query_as!("SELECT id, name FROM users WHERE id = $1", 1)
    .fetch_one(&pool).await?;

このコードは、指定されたユーザーIDのユーザー情報を取得します。

トランザクションの利用と管理

トランザクションを使用すると、複数の操作を一つの論理的な単位としてまとめることができます。
以下は、トランザクションを使用した例です:

let mut tx = pool.begin().await?;
sqlx::query!("INSERT INTO users (name, email) VALUES ($1, $2)", "Grace", "grace@example.com")
    .execute(&mut tx).await?;
sqlx::query!("INSERT INTO orders (user_id, item) VALUES ($1, $2)", 1, "Item2")
    .execute(&mut tx).await?;
tx.commit().await?;

このコードは、ユーザー情報と注文情報をトランザクション内で挿入し、全ての操作が成功した場合にコミットします。

エラーハンドリングとデバッグ方法

クエリ実行中にエラーが発生した場合、適切なエラ

ーハンドリングが必要です。
SQLxは詳細なエラーメッセージを提供するため、デバッグが容易です。
以下は、エラーをキャッチして処理する例です:

if let Err(e) = sqlx::query!("INSERT INTO users (name, email) VALUES ($1, $2)", "Henry", "henry@example.com")
    .execute(&pool).await {
    eprintln!("Error occurred: {}", e);
}

このコードは、INSERT操作中に発生したエラーをキャッチし、エラーメッセージを出力します。

SQLx::queryの使い方と効率的なクエリ作成方法

SQLx::queryは、RustでSQLクエリを実行するための便利なツールです。
SQLx::queryを使用することで、安全で効率的にクエリを作成し、データベース操作を行うことができます。

use sqlx::postgres::PgPoolOptions;

#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
    let pool = PgPoolOptions::new()
        .max_connections(5)
        .connect("postgres://user:password@localhost/database").await?;

    let row: (i32, String) = sqlx::query_as!("SELECT id, name FROM users WHERE id = $1", 1)
        .fetch_one(&pool).await?;
    
    println!("User ID: {}, Name: {}", row.0, row.1);
    Ok(())
}

上記のコードは、SQLx::queryを使用してPostgreSQLデータベースからユーザー情報を取得する例です。

SQLx::queryの基本概念

SQLx::queryは、RustでSQLクエリを実行するための主要な手段です。
基本的なクエリの作成と実行をサポートし、コンパイル時にクエリを検証します。
これにより、安全でエラーが少ないコードを作成することができます。

シンプルなクエリの作成方法

シンプルなクエリを作成するには、`sqlx::query!`マクロを使用します。
以下のコードは、簡単なSELECTクエリを実行する例です:

let row: (i32, String) = sqlx::query_as!("SELECT id, name FROM users WHERE id = $1", 1)
    .fetch_one(&pool).await?;

このコードは、指定されたユーザーIDのユーザー情報を取得します。

複雑なクエリの作成と管理

複雑なクエリもSQLx::queryを使用して管理することができます。
以下は、複数のテーブルを結合するクエリの例です:

let rows = sqlx::query!(
    "SELECT users.id, users.name, orders.id AS order_id, orders.item 
     FROM users 
     JOIN orders ON users.id = orders.user_id 
     WHERE users.id = $1", 1)
    .fetch_all(&pool).await?;

このコードは、指定されたユーザーIDのユーザーとその注文情報を取得します。

パフォーマンスを向上させるクエリ最適化

クエリのパフォーマンスを向上させるためには、以下のポイントを考慮します:
– インデックスの適切な使用
– 不必要なデータの取得を避ける
– クエリの最適化

例えば、インデックスを追加することで、クエリのパフォーマンスを向上させることができます:

CREATE INDEX idx_users_name ON users(name);

クエリのデバッグとエラーハンドリング

クエリ実行中にエラーが発生した場合、適切なエラーハンドリングが必要です。
SQLxは詳細なエラーメッセージを提供するため、デバッグが容易です。
以下は、エラーをキャッチして処理する例です:

if let Err(e) = sqlx::query!("INSERT INTO users (name, email) VALUES ($1, $2)", "Ivy", "ivy@example.com")
    .execute(&pool).await {
    eprintln!("Error occurred: {}", e);
}

このコードは、INSERT操作中に発生したエラーをキャッチし、エラーメッセージを出力します。

資料請求

RELATED POSTS 関連記事