28 个版本
0.6.2 | 2024 年 6 月 26 日 |
---|---|
0.6.0 | 2024 年 5 月 20 日 |
0.5.7 | 2023 年 1 月 30 日 |
0.5.6 | 2022 年 8 月 9 日 |
0.0.2 | 2017 年 10 月 31 日 |
#25 在 数据库接口 中
6,059 每月下载量
用于 10 个 Crates(9 个直接使用)
3MB
57K SLoC
Rust-oracle
这是一个基于 Oracle 数据库 和 Rust 的 ODPI-C 的数据库驱动程序。
变更日志
请参阅 ChangeLog.md。
构建时要求
- 编译器。请参阅 此文档中的编译时要求。
运行时要求
- Oracle 客户端 11.2 或更高版本。请参阅 ODPI-C 安装文档。
支持的 Rust 版本
Oracle crate 支持 至少 6 个 Rust 小版本,包括 crate 发布时的稳定版本。当进行补丁版本升级时,MSRV(最低支持 Rust 版本)可能会更改,尽管它不会频繁更改。当前的 MSRV 是 1.60.0。
使用方法
将以下内容放入您的 Cargo.toml
[dependencies]
oracle = "0.6.2"
可选功能
以下功能可以从 Cargo.toml 启用
功能 | 描述 | 可用版本 |
---|---|---|
chrono |
为 chrono 数据类型实现 ToSql 和 FromSql 。 |
any |
stmt_without_lifetime |
从 Statement 中移除 conn 生命周期。这可以避免生命周期冲突。 |
0.5.7 仅限 |
aq_unstable |
启用 Oracle 高级队列支持。这是不稳定的。它可能会在次要版本升级中以不兼容的方式更改。 | 自 0.5.5 |
示例
执行选择语句并获取行
use oracle::{Connection, Error};
// Connect to a database.
let conn = Connection::connect("scott", "tiger", "//localhost/XE")?;
let sql = "select ename, sal, comm from emp where deptno = :1";
// Select a table with a bind variable.
println!("---------------|---------------|---------------|");
let rows = conn.query(sql, &[&30])?;
for row_result in rows {
let row = row_result?;
// get a column value by position (0-based)
let ename: String = row.get(0)?;
// get a column by name (case-insensitive)
let sal: i32 = row.get("sal")?;
// Use `Option<...>` to get a nullable column.
// Otherwise, `Err(Error::NullValue)` is returned
// for null values.
let comm: Option<i32> = row.get(2)?;
println!(" {:14}| {:>10} | {:>10} |",
ename,
sal,
comm.map_or("".to_string(), |v| v.to_string()));
}
// Another way to fetch rows.
// The rows iterator returns Result<(String, i32, Option<i32>)>.
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::<(), oracle::Error>(())
执行选择语句并获取第一行
use oracle::Connection;
// Connect to a database.
let conn = Connection::connect("scott", "tiger", "//localhost/XE")?;
let sql = "select ename, sal, comm from emp where empno = :1";
// Print the first row.
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()));
// When no rows are found, conn.query_row() returns `Err(Error::NoDataFound)`.
// Get the first row as a tupple
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::<(), oracle::Error>(())
执行非选择语句
use oracle::Connection;
// Connect to a database.
let conn = Connection::connect("scott", "tiger", "//localhost/XE")?;
conn.execute("create table person (id number(38), name varchar2(40))", &[])?;
// Execute a statement with positional parameters.
conn.execute("insert into person values (:1, :2)",
&[&1, // first parameter
&"John" // second parameter
])?;
// Execute a statement with named parameters.
conn.execute_named("insert into person values (:id, :name)",
&[("id", &2), // 'id' parameter
("name", &"Smith"), // 'name' parameter
])?;
// Commit the transaction.
conn.commit()?;
// Delete rows
conn.execute("delete from person", &[])?;
// Rollback the transaction.
conn.rollback()?;
# Ok::<(), oracle::Error>(())
打印列信息
use oracle::Connection;
// Connect to a database.
let conn = Connection::connect("scott", "tiger", "//localhost/XE")?;
let sql = "select ename, sal, comm from emp where 1 = 2";
let rows = conn.query(sql, &[])?;
// Print column names
for info in rows.column_info() {
print!(" {:14}|", info.name());
}
println!("");
// Print column types
for info in rows.column_info() {
print!(" {:14}|", info.oracle_type().to_string());
}
println!("");
# Ok::<(), oracle::Error>(())
预编译语句
use oracle::Connection;
let conn = Connection::connect("scott", "tiger", "//localhost/XE")?;
// Create a prepared statement
let mut stmt = conn.statement("insert into person values (:1, :2)").build()?;
// Insert one row
stmt.execute(&[&1, &"John"])?;
// Insert another row
stmt.execute(&[&2, &"Smith"])?;
# Ok::<(), oracle::Error>(())
这比两个 conn.execute()
更高效。以下是在 DBMS 中执行 SQL 语句的示例
- 步骤 1. 解析 SQL 语句并创建执行计划。
- 步骤 2. 使用绑定参数执行计划。
当使用预编译语句时,步骤 1 只调用一次。
NLS_LANG 参数
NLS_LANG 包含三个组件:语言、地区和字符集。然而,字符集组件被忽略,因为 Rust 字符是 UTF-8,所以使用 UTF-8(AL32UTF8) 作为字符集。
地区组件指定数字格式、日期格式等。然而,它仅影响 Oracle 中的转换。请参见以下示例
use oracle::Connection;
// The territory is France.
std::env::set_var("NLS_LANG", "french_france.AL32UTF8");
let conn = Connection::connect("scott", "tiger", "")?;
// 10.1 is converted to a string in Oracle and fetched as a string.
let result = conn.query_row_as::<String>("select to_char(10.1) from dual", &[])?;
assert_eq!(result, "10,1"); // The decimal mark depends on the territory.
// 10.1 is fetched as a number and converted to a string in rust-oracle
let result = conn.query_row_as::<String>("select 10.1 from dual", &[])?;
assert_eq!(result, "10.1"); // The decimal mark is always period(.).
# Ok::<(), oracle::Error>(())
请注意,如果需要,必须在第一次执行 rust-oracle 函数之前设置 NLS_LANG。
待办事项
- BFILEs(外部 LOB)(注意:支持将 BFILEs 的内容读取为
Vec<u8>
) - 可滚动游标
- 更好的 Oracle 对象类型支持
- XML 数据类型
- JSON 数据类型
相关项目
其他连接到 Oracle 的 crate
- Sibyl:一个基于 OCI 的接口,支持阻塞(线程)和非阻塞(异步)API
Oracle 相关 crate
- bb8-oracle:为 Oracle 提供的 bb8 连接池支持
- diesel-oci:为 Diesel 实现的 Oracle SQL 数据库后端
- include-oracle-sql:使用 Sibyl 的 include-sql 扩展,用于数据库访问
- r2d2-oracle:为 r2d2 连接池提供 Oracle 支持
许可证
Rust-oracle 和 ODPI-C 以 rust-oracle 的条款捆绑在一起
依赖关系
~1.6–7.5MB
~54K SLoC