Rust Oracle数据库驱动库oracle的使用,支持高效连接和操作Oracle数据库的Rust插件库
Rust Oracle数据库驱动库oracle的使用
这是一个基于ODPI-C的Rust Oracle数据库驱动库,支持高效连接和操作Oracle数据库。
编译要求
- C编译器
运行时要求
- Oracle客户端11.2或更高版本
支持的Rust版本
oracle crate至少支持6个Rust次要版本,包括发布时的稳定版本。当前最低支持的Rust版本是1.60.0。
使用方法
在Cargo.toml
中添加:
[dependencies]
oracle = "0.6.3"
可选功能
功能 | 描述 | 可用版本 |
---|---|---|
chrono |
为chrono数据类型实现ToSql 和FromSql |
任何 |
stmt_without_lifetime |
从Statement 中移除conn 生命周期 |
仅0.5.7 |
aq_unstable |
启用Oracle高级队列支持(不稳定) | 0.5.5起 |
示例代码
执行查询语句并获取结果
use oracle::{Connection, Error};
// 连接数据库
let conn = Connection::connect("scott", "tiger", "//localhost/XE")?;
let sql = "select ename, sal, comm from emp where deptno = :1";
// 使用绑定变量查询表
println!("---------------|---------------|---------------|");
let rows = conn.query(sql, &[&30])?;
for row_result in rows {
let row = row_result?;
// 通过位置获取列值(0-based)
let ename: String = row.get(0)?;
// 通过列名获取(不区分大小写)
let sal: i32 = row.get("sal")?;
// 使用`Option<...>`获取可空列
let comm: Option<i32> = row.get(2)?;
println!(" {:14}| {:>10} | {:>10} |",
ename,
sal,
comm.map_or("".to_string(), |v| v.to_string()));
}
// 另一种获取行的方式
println!("---------------|---------------|---------------|");
let rows = conn.query_as::<(String, i32, Option<i32>)>(sql, &[&10])?;
for row_result in rows {
let (ename, sal, comm) = row_result?;
println!(" {:14}| {:>10} | {:>10} |",
ename,
sal,
comm.map_or("".to_string(), |v| v.to_string()));
}
Ok::<(), Error>(())
执行查询并获取第一行
use oracle::Connection;
// 连接数据库
let conn = Connection::connect("scott", "tiger", "//localhost/XE")?;
let sql = "select ename, sal, comm from emp where empno = :1";
// 打印第一行
let row = conn.query_row(sql, &[&7369])?;
let ename: String = row.get("empno")?;
let sal: i32 = row.get("sal")?;
let comm: Option<i32> = row.get("comm")?;
println!("---------------|---------------|---------------|");
println!(" {:14}| {:>10} | {:>10} |",
ename,
sal,
comm.map_or("".to_string(), |v| v.to_string()));
// 获取第一行作为元组
let row = conn.query_row_as::<(String, i32, Option+i32>)>(sql, &[&7566])?;
println!("---------------|---------------|---------------|");
println!(" {:14}| {:>10} | {:>10} |",
row.0,
row.1,
row.2.map_or("".to_string(), |v| v.to_string()));
Ok::<(), Error>(())
执行非查询语句
use oracle::Connection;
// 连接数据库
let conn = Connection::connect("scott", "tiger", "//localhost/XE")?;
conn.execute("create table person (id number(38), name varchar2(40))", &[])?;
// 使用位置参数执行语句
conn.execute("insert into person values (:1, :2)",
&[&1, // 第一个参数
&"John" // 第二个参数
])?;
// 使用命名参数执行语句
conn.execute_named("insert into person values (:id, :name)",
&[("id", &2), // 'id'参数
("name", &"Smith"), // 'name'参数
])?;
// 提交事务
conn.commit()?;
// 删除行
conn.execute("delete from person", &[])?;
// 回滚事务
conn.rollback()?;
Ok::<(), Error>(())
打印列信息
use oracle::Connection;
// 连接数据库
let conn = Connection::connect("scott", "tiger", "//localhost/XE")?;
let sql = "select ename, sal, comm from emp where 1 = 2";
let rows = conn.query(sql, &[])?;
// 打印列名
for info in rows.column_info() {
print!(" {:14}|", info.name());
}
println!("");
// 打印列类型
for info in rows.column_info() {
print!(" {:14}|", info.oracle_type().to_string());
}
println!("");
Ok::<(), Error>(())
预编译语句
use oracle::Connection;
let conn = Connection::connect("scott", "tiger", "//localhost/XE")?;
// 创建预编译语句
let mut stmt = conn.statement("insert into person values (:1, :2)").build()?;
// 插入一行
stmt.execute(&[&1, &"John"])?;
// 插入另一行
stmt.execute(&[&2, &"Smith"])?;
Ok::<(), Error>(())
NLS_LANG参数
NLS_LANG由三个部分组成:语言、地区和字符集。但是字符集部分会被忽略,因为Rust字符是UTF-8编码的。
地区部分指定数字格式、日期格式等,但它只影响Oracle中的转换。
完整示例
以下是一个完整的Oracle数据库操作示例,包含连接、创建表、插入数据、查询数据和事务管理:
use oracle::{Connection, Error};
fn main() -> Result<(), Error> {
// 连接Oracle数据库
let conn = Connection::connect("username", "password", "//localhost:1521/ORCL")?;
// 创建表
conn.execute("CREATE TABLE rust_test (id NUMBER, name VARCHAR2(50))", &[])?;
// 插入数据 - 使用位置参数
conn.execute("INSERT INTO rust_test VALUES (:1, :2)", &[&1, &"Alice"])?;
// 插入数据 - 使用命名参数
conn.execute_named(
"INSERT INTO rust_test VALUES (:id, :name)",
&[("id", &2), ("name", &"Bob")]
)?;
// 提交事务
conn.commit()?;
// 查询数据
println!("ID | NAME");
println!("---+------");
let rows = conn.query("SELECT id, name FROM rust_test ORDER BY id", &[])?;
for row_result in rows {
let row = row_result?;
let id: i32 = row.get(0)?;
let name: String = row.get(1)?;
println!("{:2} | {}", id, name);
}
// 预编译语句示例
let mut stmt = conn.statement("INSERT INTO rust_test VALUES (:1, :2)").build()?;
for i in 3..=5 {
stmt.execute(&[&i, &format!("User {}", i)])?;
}
conn.commit()?;
// 删除表
conn.execute("DROP TABLE rust_test", &[])?;
Ok(())
}
这个示例展示了:
- 数据库连接
- 表创建
- 两种参数绑定方式插入数据
- 事务管理(commit)
- 数据查询和结果处理
- 预编译语句使用
- 表删除
注意在实际使用时,请替换连接字符串中的用户名、密码和数据库服务名。
1 回复
Rust Oracle数据库驱动库oracle使用指南
介绍
oracle
是一个纯Rust实现的Oracle数据库驱动库,提供了高效连接和操作Oracle数据库的能力。该库支持OCI (Oracle Call Interface)协议,不需要额外的Oracle客户端软件,是Rust生态中与Oracle数据库交互的主要解决方案。
主要特性
- 纯Rust实现,无需Oracle客户端
- 支持连接池
- 支持异步操作(async/await)
- 类型安全的API设计
- 支持LOB、JSON等Oracle特有数据类型
- 兼容Oracle 11g及以上版本
安装
在Cargo.toml中添加依赖:
[dependencies]
oracle = "0.7"
基本使用方法
1. 建立连接
use oracle::{Connection, Error};
fn main() -> Result<(), Error> {
// 基本连接
let conn = Connection::connect("username", "password", "//hostname:port/service_name")?;
// 带连接选项的连接
let conn = Connection::connect(
"username",
"password",
"//hostname:1521/ORCL",
&[
("pool_min", "2"),
("pool_max", "10"),
("stmt_cache_size", "50"),
],
)?;
Ok(())
}
2. 执行查询
use oracle::{Connection, Error};
fn main() -> Result<(), Error> {
let conn = Connection::connect("scott", "tiger", "//localhost:1521/ORCL")?;
// 简单查询
let rows = conn.query("select empno, ename, sal from emp where deptno = :1", &[&极光]",
)?;
for row_result in rows {
let row = row_result?;
let empno: i32 = row.get("empno")?;
let ename: String = row.get("ename")?;
let sal: Option<f64> = row.get("sal")?;
println!("empno: {}, ename: {}, sal: {:?}", empno, ename, sal);
}
Ok(())
}
3. 执行DML操作
use oracle::{Connection, Error};
fn main() -> Result极光(), Error> {
let conn = Connection::connect("scott", "tiger", "//localhost极光521/ORCL")?;
// 插入数据
conn.execute(
"insert into emp (empno, ename, job, sal) values (:1, :2, :3, :4)",
&[&1234, &"SMITH", &"CLERK", &800.0],
)?;
// 更新数据
let rows_updated = conn.execute(
"update emp set sal = sal * 1.1 where deptno = :1",
&[&20],
)?;
println!("Updated {} rows", rows_updated);
// 提交事务
conn.commit()?;
Ok(())
}
4. 使用预处理语句
use oracle::{Connection, Error};
fn main() -> Result<(), Error> {
let conn = Connection::connect("scott", "tiger", "//localhost:1521/ORCL")?;
// 创建预处理语句
let mut stmt = conn.statement("insert into dept (deptno, dname, loc) values (:1, :2, :3)").build()?;
// 批量插入
stmt.execute(&[&10, &"ACCOUNTING", &"NEW YORK"])?;
stmt.execute(&[&20, &"RESEARCH", &"DALLAS"])?;
stmt.execute(&[&30, &"SALES", &"CHICAGO"])?;
stmt.execute(&[&40, &"OPERATIONS", &"BOSTON"])?;
conn.commit()?;
Ok(())
}
5. 使用连接池
use oracle::{Connection, Error, Pool};
fn main() -> Result<(), Error> {
// 创建连接池
let pool = Pool::new(
"scott",
"tiger",
"//localhost:1521/ORCL",
PoolOptions::new().max_connections(10),
)?;
// 从池中获取连接
let conn = pool.get()?;
// 使用连接...
let result = conn.query_row("select sysdate from dual", &[])?;
let sysdate: oracle::Timestamp = result.get(0)?;
println!("Current date: {}", sysdate);
// 连接会自动返回到池中
Ok(())
}
6. 异步操作
use oracle::{Connection, Error};
use tokio::runtime::Runtime;
async fn async_query() -> Result<(), Error> {
let conn = Connection::connect("scott", "tiger", "//localhost:1521/ORCL").await?;
let rows = conn.query("select empno, ename from emp", &[]).await?;
for row_result in rows {
let row = row_result?;
let empno: i32 = row.get("empno")?;
let ename: String = row.get("ename")?;
println!("empno: {}, ename: {}", empno, ename);
}
Ok(())
}
fn main() -> Result<(), Error> {
let rt = Runtime::new()?;
rt.block_on(async_query())
}
高级特性
处理LOB数据
use oracle::{Connection, Error};
fn main() -> Result<(), Error> {
let conn = Connection::connect("scott", "tiger", "//localhost:1521/ORCL")?;
// 插入CLOB数据
let clob_data = "This is a large text...".repeat(100);
conn.execute(
"insert into documents (id, content) values (:1, :2)",
&[&1, &clob_data],
)?;
// 读取CLOB数据
let row = conn.query_row(
"select content from documents where id = :1",
&[&1],
)?;
let content: String = row.get("content")?;
println!("Document content length: {}", content.len());
Ok(())
}
处理JSON数据
use oracle::{Connection, Error};
use serde_json::{json, Value};
fn main() -> Result<(), Error> {
let conn = Connection::connect("scott", "tiger", "//localhost:1521/ORCL")?;
// 插入JSON数据
let json_data = json!({
"name": "John Doe",
"age": 30,
"address": {
"street": "123 Main St",
"city": "Anytown"
}
});
conn.execute(
"insert into customer_data (id, data) values (:1, :2)",
&[&1, &json_data.to_string()],
)?;
// 查询并解析JSON数据
let row = conn.query_row(
"select data from customer_data where id = :1",
&[&1],
)?;
let json_str: String极光ow.get("data")?;
let parsed: Value = serde_json::from_str(&json_str)?;
println!("Customer name: {}", parsed["name"]);
Ok(())
}
完整示例
以下是一个完整的Rust Oracle数据库操作示例,展示了连接、查询、插入和事务处理:
use oracle::{Connection, Error};
use serde_json::json;
fn main() -> Result<(), Error> {
// 1. 建立数据库连接
let conn = Connection::connect(
"scott",
"tiger",
"//localhost:1521/ORCL",
&[("stmt_cache_size", "50")],
)?;
// 2. 创建测试表
conn.execute("create table rust_test (id number, name varchar2(50), data clob, json_data clob)", &[])?;
// 3. 插入数据
let clob_data = "这是一个CLOB测试数据".repeat(100);
let json_data = json!({
"project": "Oracle Rust Driver",
"version": "0.7",
"features": ["async", "pool", "typesafe"]
});
conn.execute(
"insert into rust_test (id, name, data, json_data) values (:1, :2, :3, :4)",
&[&1, &"测试数据", &clob_data, &json_data.to_string()],
)?;
// 4. 查询数据
println!("\n查询结果:");
let rows = conn.query("select id, name, dbms_lob.getlength(data) as data_len from rust_test", &[])?;
for row_result in rows {
let row = row_result?;
let id: i32 = row.get("id")?;
let name: String = row.get("name")?;
let data_len: i64 = row.get("data_len")?;
println!("ID: {}, Name: {}, Data长度: {}", id, name, data_len);
}
// 5. 事务处理示例
match conn.execute("update rust_test set name = '更新后的名称' where id = 1", &[]) {
Ok(rows_updated) => {
println!("\n成功更新{}行数据", rows_updated);
conn.commit()?;
}
Err(e) => {
println!("\n更新失败: {}", e);
conn.rollback()?;
}
}
// 6. 清理测试表
conn.execute("drop table rust_test purge", &[])?;
Ok(())
}
注意事项
- 确保Oracle数据库服务正常运行且网络可达
- 对于生产环境,建议使用连接池管理数据库连接
- 处理大结果集时考虑使用流式获取(如
query_as_stream
) - 注意事务管理,及时提交或回滚
- 错误处理应使用
oracle::Error
类型
这个库提供了丰富的功能来满足大多数Oracle数据库操作需求,更多高级用法可以参考官方文档。