MySQL是一個(gè)廣泛使用的關(guān)系型數(shù)據(jù)庫(kù),Rust作為一門(mén)相對(duì)較新的系統(tǒng)級(jí)編程語(yǔ)言,具有C語(yǔ)言般的高性能、安全、并發(fā)等特性,因此與MySQL一起使用是一種非常有趣的選擇。在本教程中,我們將手把手地展示如何在Rust中連接和使用MySQL數(shù)據(jù)庫(kù)。
安裝 mysql
模塊
這里我們假設(shè)你已經(jīng)安裝了Rust編程語(yǔ)言工具鏈,在本教程中,我們將使用mysql
crate來(lái)連接和使用MySQL數(shù)據(jù)庫(kù)。要安裝mysql
crate,我們可以使用Rust語(yǔ)言包管理器cargo
,只需在終端中輸入以下命令:
cargo install mysql
安裝成功后,我們可以開(kāi)始嘗試連接MySQL數(shù)據(jù)庫(kù)了。
連接MySQL數(shù)據(jù)庫(kù)
首先,我們需要安裝和配置MySQL數(shù)據(jù)庫(kù),以便在Rust程序中進(jìn)行連接。安裝和配置MySQL在此處不做敘述。
在Rust程序中使用mysql
crate庫(kù)連接MySQL數(shù)據(jù)庫(kù),需要進(jìn)行以下步驟:
- 導(dǎo)入
mysql
crate
- 導(dǎo)入
- 使用
mysql::OptsBuilder
設(shè)置MySQL連接選項(xiàng)
- 使用
- 使用
mysql::Pool::new
創(chuàng)建MySQL連接池
- 使用
- 使用
pool.get_conn()
獲取MySQL連接,并進(jìn)行一些操作,例如插入、查詢(xún)等
- 使用
- 使用
pool.disconnect()
斷開(kāi)MySQL連接
- 使用
下面是連接MySQL數(shù)據(jù)庫(kù)的示例代碼:
use mysql::*;
fn main() {
let opts = OptsBuilder::new()
.ip_or_hostname(Some("localhost"))
.user(Some("root"))
.pass(Some("password"))
.db_name(Some("test"))
.tcp_port(3306);
let pool = Pool::new(opts).unwrap();
let mut conn = pool.get_conn().unwrap();
let result = conn.query_first("SELECT * FROM users").unwrap();
for row in result {
let name: String = row.get("name").unwrap();
let age: i32 = row.get("age").unwrap();
println!("{} is {} years old", name, age);
}
pool.disconnect().unwrap();
}
以上代碼創(chuàng)建了一個(gè)MySQL連接池,并從連接池中獲取一個(gè)MySQL連接,查詢(xún)了一個(gè)名為users
的表,并將結(jié)果作為元素進(jìn)行遍歷。
Rust使用MySQL的進(jìn)階用法
事務(wù)(Transaction)
為了保證MySQL數(shù)據(jù)庫(kù)中的數(shù)據(jù)一致性,我們通常需要使用事務(wù)(Transaction)。在Rust中,可以使用MySQL的事務(wù)功能并結(jié)合mysql::Transaction
來(lái)實(shí)現(xiàn)。
使用以下代碼示例可以體驗(yàn)事務(wù)的實(shí)現(xiàn):
use mysql::*;
fn main() {
let opts = OptsBuilder::new()
.ip_or_hostname(Some("localhost"))
.user(Some("root"))
.pass(Some("password"))
.db_name(Some("test"))
.tcp_port(3306);
let pool = Pool::new(opts).unwrap();
let mut conn = pool.get_conn().unwrap();
// Start a transaction
let mut transaction = conn.start_transaction(TxOpts::default()).unwrap();
// Insert data into a table
transaction .prep_exec("INSERT INTO users (name, age) VALUES (?, ?)", ("Alice", 23)).unwrap();
transaction.prep_exec("INSERT INTO users (name, age) VALUES (?, ?)", ("Bob", 25)).unwrap();
// Commit a transaction
transaction.commit().unwrap();
// Select data from a table let result = conn.query("SELECT * FROM users").unwrap();
for row in result {
let name: String = row.get("name").unwrap();
let age: i32 = row.get("age").unwrap();
println!("{} is {} years old", name, age);
}
pool.disconnect().unwrap();
}
以上代碼創(chuàng)建了一個(gè)名為users
的表,并在事務(wù)內(nèi)分別插入了兩個(gè)元素,數(shù)據(jù)被成功提交到了MySQL數(shù)據(jù)庫(kù),我們看到了名為Alice
和Bob
的條目。
異步IO
Rust語(yǔ)言具有異步IO處理的優(yōu)勢(shì)。在Rust中使用MySQL異步IO時(shí),可以使用tokio-mysql
crate來(lái)實(shí)現(xiàn)。tokio-mysql
crate是一個(gè)基于Tokio實(shí)現(xiàn)的異步MySQL數(shù)據(jù)庫(kù)客戶(hù)端。
下面是使用tokio-mysql
crate的示例代碼:
use std::str::FromStr;
use tokio::runtime::Builder;
use tokio::time::Duration;
use tokio_mysql::{prelude::*, Error, Opts, Pool};
#[tokio::main]
async fn main() - > Result< (), Error > {
let opts = Opts::from_url("mysql://root:password@localhost:3306/test")?;
let pool = Pool::new(opts);
let pool = match pool {
Ok(p) = > p,
Err(e) = > return Err(e),
};
let mut conn = pool.get_conn().await?;
conn.query_drop("CREATE TABLE IF NOT EXISTS students (
id INT PRIMARY KEY NOT NULL,
name TEXT NOT NULL,
age INT NOT NULL
)")
.await?;
let id = 1;
let name = "Alice";
let age = 23;
conn.exec_drop(
format!(
"INSERT INTO students (id, name, age) VALUES ({}, "{}", {})",
id, name, age
)
.as_str()
)
.await?;
let mut conn2 = pool.get_conn().await?;
let result = conn2
.query_iter(
String::from("SELECT * FROM students")
.as_str(),
)
.await?;
for row in result {
let id: u32 = row.unwrap().take("id").unwrap().as_integer().unwrap().try_into().unwrap();
let name: &str = row.unwrap().take("name").unwrap().as_sql_str();
let age: u32 = row.unwrap().take("age").unwrap().as_integer().unwrap().try_into().unwrap();
println!("{} is {} years old", name, age);
}
Ok(())
}
它創(chuàng)建了一個(gè)名為students
的表,并插入了一個(gè)名為Alice
年齡為23
的元素,然后遍歷該表并打印結(jié)果。
Rust使用MySQL的最佳實(shí)踐
連接池
在連接MySQL數(shù)據(jù)庫(kù)時(shí),使用連接池是非常重要的。連接池是一個(gè)預(yù)先創(chuàng)建的連接集合,由于預(yù)先初始化了這些連接,因此在保持連接上下文的情況下執(zhí)行多個(gè)操作變得更加輕松。在Rust中使用mysql::Pool
連接MySQL數(shù)據(jù)庫(kù)是非常常見(jiàn)的。
let opts = OptsBuilder::new()
.ip_or_hostname(Some("localhost"))
.user(Some("root"))
.pass(Some("password"))
.db_name(Some("test"))
.tcp_port(3306);
let pool = Pool::new(opts).unwrap();
避免SQL注入
避免SQL注入攻擊是一個(gè)重要的安全問(wèn)題。在Rust中使用mysql
crate,可以使用mysql::from_value
和mysql::Value::from
方法來(lái)避免SQL注入攻擊。
在Rust中,需要使用以下代碼實(shí)現(xiàn)SQL語(yǔ)句中的參數(shù)綁定:
let name = "Alice";
let age = 23;
conn.prep_exec("INSERT INTO students (name, age) VALUES (?, ?)", (name, age),).unwrap();
在將參數(shù)傳遞給SQL查詢(xún)時(shí),需要使用mysql::Value::from
方法將變量轉(zhuǎn)換為mysql::Value
類(lèi)型,以防止SQL注入攻擊。要從mysql::Value
轉(zhuǎn)換回常規(guī)變量,可以使用mysql::from_value
方法。使用以下示例代碼:
use mysql::*;
fn main() {
let result: Vec< Row > = conn.query("SELECT * FROM students WHERE age >= ?", (age.into(),)).unwrap();
for row in result {
let age: i32 = from_value(row.get("age").unwrap());
let name: String = from_value(row.get("name").unwrap());
println!("{} is {} years old", name, age);
}
}
SQL執(zhí)行和結(jié)果處理
在Rust中,可以使用mysql::Conn::query
,mysql::Conn::exec_iter
和mysql::Conn::prep_exec
等方法來(lái)執(zhí)行SQL語(yǔ)句。但是,這些方法返回的結(jié)果類(lèi)型有很大不同。query
方法返回包含所有結(jié)果集的Vec
類(lèi)型,而exec_iter
方法返回mysql::Row
類(lèi)型的迭代器。最后,prep_exec
方法是最常用的方法,它可以綁定參數(shù),并類(lèi)似于通過(guò)命令行客戶(hù)端發(fā)送的查詢(xún),并返回mysql::QueryResult
類(lèi)型。如果要提取單個(gè)結(jié)果,可以使用mysql::QueryResult
的方法mysql::QueryResult::next
來(lái)獲取。
使用以下代碼示例說(shuō)明不同方法的使用:
use mysql::*;
fn main() {
let result: Vec< Row > = conn.query("SELECT * FROM students WHERE age >= ?", (age.into(),)).unwrap();
for row in result {
let age: i32 = from_value(row.get("age").unwrap());
let name: String = from_value(row.get("name").unwrap());
println!("{} is {} years old", name, age);
}
let mut iter = conn.exec_iter("SELECT age FROM students WHERE name = "Alice"").unwrap();
while let Some(result) = iter.next() {
let age: i32 = from_value(result.unwrap());
println!("Alice is {} years old", age);
}
conn.prep_exec("INSERT INTO students (name, age) VALUES (?, ?)",(name, age),).unwrap();
}
結(jié)論
本教程介紹了如何在Rust中連接和使用MySQL數(shù)據(jù)庫(kù)。我們學(xué)習(xí)了使用mysql
crate連接MySQL數(shù)據(jù)庫(kù),并實(shí)現(xiàn)了一些常見(jiàn)用例,例如事務(wù)、異步IO等。此外,我們使用連接池、避免SQL注入技巧,并使用了不同的SQL執(zhí)行和結(jié)果處理方法。如果你正在使用Rust編程語(yǔ)言,那么通過(guò)學(xué)習(xí)本教程,你將掌握基本和高級(jí)的連接和使用MySQL技巧。
-
C語(yǔ)言
+關(guān)注
關(guān)注
183文章
7634瀏覽量
143865 -
編程語(yǔ)言
+關(guān)注
關(guān)注
10文章
1957瀏覽量
38332 -
管理器
+關(guān)注
關(guān)注
0文章
264瀏覽量
19391 -
MYSQL數(shù)據(jù)庫(kù)
+關(guān)注
關(guān)注
0文章
96瀏覽量
10102 -
Rust
+關(guān)注
關(guān)注
1文章
237瀏覽量
7393
發(fā)布評(píng)論請(qǐng)先 登錄
labview 連接mysql 數(shù)據(jù)庫(kù)的問(wèn)題
labview連接mysql數(shù)據(jù)庫(kù)的問(wèn)題
如何使用原生hqc連接MySQL數(shù)據(jù)庫(kù)
python如何連接MySql數(shù)據(jù)庫(kù)
ESP8266如何連接mysql數(shù)據(jù)庫(kù)
PHP教程之PHP與MySQL數(shù)據(jù)庫(kù)連接的資料說(shuō)明

華為云數(shù)據(jù)庫(kù)-RDS for MySQL數(shù)據(jù)庫(kù)
MySQL數(shù)據(jù)庫(kù)管理與應(yīng)用
mysql數(shù)據(jù)庫(kù)基礎(chǔ)命令
eclipse怎么連接數(shù)據(jù)庫(kù)mysql
數(shù)據(jù)庫(kù)數(shù)據(jù)恢復(fù)—Mysql數(shù)據(jù)庫(kù)表記錄丟失的數(shù)據(jù)恢復(fù)流程

MySQL數(shù)據(jù)庫(kù)的安裝

適用于MySQL和MariaDB的Python連接器:可靠的MySQL數(shù)據(jù)連接器和數(shù)據(jù)庫(kù)

從Delphi、C++ Builder和Lazarus連接到MySQL數(shù)據(jù)庫(kù)

評(píng)論