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数据库接口

Download history 1467/week @ 2024-05-02 1207/week @ 2024-05-09 1628/week @ 2024-05-16 1551/week @ 2024-05-23 1623/week @ 2024-05-30 1289/week @ 2024-06-06 1233/week @ 2024-06-13 1741/week @ 2024-06-20 1329/week @ 2024-06-27 1240/week @ 2024-07-04 1101/week @ 2024-07-11 1142/week @ 2024-07-18 1343/week @ 2024-07-25 1588/week @ 2024-08-01 1561/week @ 2024-08-08 1327/week @ 2024-08-15

6,059 每月下载量
用于 10 个 Crates(9 个直接使用)

UPL-1.0/Apache-2.0

3MB
57K SLoC

C 38K SLoC // 0.2% comments Rust 17K SLoC // 0.0% comments SQL 2K SLoC // 0.1% comments Python 130 SLoC // 0.5% comments Shell 36 SLoC // 0.4% comments

Rust-oracle

Test Crates.io Docs Docs (in development)

这是一个基于 Oracle 数据库RustODPI-C 的数据库驱动程序。

变更日志

请参阅 ChangeLog.md

构建时要求

运行时要求

支持的 Rust 版本

Oracle crate 支持 至少 6 个 Rust 小版本,包括 crate 发布时的稳定版本。当进行补丁版本升级时,MSRV(最低支持 Rust 版本)可能会更改,尽管它不会频繁更改。当前的 MSRV 是 1.60.0。

使用方法

将以下内容放入您的 Cargo.toml

[dependencies]
oracle = "0.6.2"

可选功能

以下功能可以从 Cargo.toml 启用

功能 描述 可用版本
chrono chrono 数据类型实现 ToSqlFromSql 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。

待办事项

其他连接到 Oracle 的 crate

  • Sibyl:一个基于 OCI 的接口,支持阻塞(线程)和非阻塞(异步)API

Oracle 相关 crate

许可证

Rust-oracle 和 ODPI-C 以 rust-oracle 的条款捆绑在一起

  1. 通用许可协议 v 1.0 或您选择的任何较新版本;以及/或
  2. Apache 许可证 v 2.0.

依赖关系

~1.6–7.5MB
~54K SLoC