如何在Rust的Diesel中编写多个显式inner_join?
使用Diesel实现显式多表Inner Join
问题背景
我用Rust的actix_web和Diesel开发API,需要实现这条SQL查询:
SELECT * FROM customers c JOIN users u ON u.name = c.customer_no JOIN address a ON c.fk_address = a.id WHERE a.name='10715';
同时有两个疑问:
- Diesel中显式连接与隐式连接的区别是什么?
- 隐式多表连接可以正常运行,但显式多连接的写法总是报错,正确的写法应该是怎样的?
显式与隐式连接的区别
- 隐式连接:依赖Diesel通过宏(如
belongs_to)预定义的表间关系,写法简洁,无需手动指定连接条件
users.inner_join(posts)
- 显式连接:不依赖预定义关系,直接在查询中明确指定连接条件,灵活性更高
users.inner_join(posts::table.on(posts::id.eq(user::id)))
我的尝试
隐式多连接写法可以正常工作:
users.inner_join(posts.inner_join(comments))
但以下显式多连接写法无法运行:
users.inner_join( posts::table.on(posts::id.eq(user::id)) .inner_join(comments::table.on(comments::id.eq(post::id))) )
解决方案
正确的显式多连接写法
Diesel中显式多连接需要让主表依次调用inner_join,每次传入带显式连接条件的目标表,不能嵌套链式调用inner_join在on子句之后。
对应目标SQL的正确代码如下:
use schema::{customers, users, address}; // 假设&conn是已建立的数据库连接 let query_results = customers::table // 显式指定customers与users的连接条件 .inner_join(users::table.on(users::name.eq(customers::customer_no))) // 显式指定customers与address的连接条件 .inner_join(address::table.on(customers::fk_address.eq(address::id))) // 添加WHERE条件 .filter(address::name.eq("10715")) // 加载为三个表的Model元组(需确保Model已正确生成) .load::<(customers::Model, users::Model, address::Model)>(&conn)?;
错误原因说明
之前的写法错误在于:posts::table.on(...)返回的是JoinOnClause类型,该类型不支持直接调用inner_join。必须让主表(或上一步的连接结果)直接调用inner_join,传入带on条件的目标表,Diesel才能正确解析多表连接逻辑。
内容的提问来源于stack exchange,提问作者ilepix
相关产品推荐
相关产品推荐

