首页 > 解决方案 > Rust rusqlite 无法插入行

问题描述

以下代码无法编译:

55 |                 (":dataset_id", &dataset_id),
   |                                 ^^^^^^^^^^^ expected `u32`, found `i32`
pub fn save(&mut self, annotations: Vec<Record>, dataset_id: i32) -> Result<(), Error> {
        let mut tx = self.conn.transaction()?;
        for record in records {
            let json: String = record();
            let sql: &str =
                "INSERT INTO records (record_id, dataset_id, value)
                 VALUES (:record_id, :dataset_id, :value)";
            let mut statement = tx.prepare(sql)?;
            statement.execute(&[
                (":record_id", &record.id),
                (":dataset_id", &dataset_id),
                (":value", "hello world")]);
        };
        tx.commit()?;
        Ok(())
}

如果我从我的 SQL 语句中删除 dataset_id 并注释掉该行:(":dataset_id", &dataset_id),

然后它无法编译:

56 |                 (":value", &"hello".to_string()),
   |                            ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found struct `std::string::String`

标签: rustrusqlite

解决方案


的参数execute是 a P: Params,即“实现的任何类型Params”。Rust 编译器不会猜测您想要的特定类型,然后相应地处理参数。相反,它只会自行解析参数的类型,然后查看它是否实现了Params.

这是你的论点:

&[(":record_id", &record.id),
  (":dataset_id", &dataset_id),
  (":value", "hello world")]

就其本身而言,类型是什么?它是对包含三个元组的数组文字的引用: a (&str, &u32)、 a(&str, &i32)和 a (&str, &str)

由于缺乏任何进一步的信息,编译器猜测第一个元素是规范元素,因此尝试相应地转换其他元素。因此,您会收到“无法转换&i32&u32”错误。

但是,您需要的是一(&str, &dyn ToSql)组元组。

所以你可以做两件事之一。

首先,将第一个参数值显式转换为正确的类型:

&[(":record_id", &record.id as &dyn ToSql),
  (":dataset_id", &dataset_id),
  (":value", "hello world")]

或者第二,使用提供的named_params!宏,rusqlite可以说更漂亮:

statement.execute(named_params!{
    ":record_id": record.id,
    ":dataset_id": dataset_id,
    ":value": "hello world",
  });

推荐阅读