如何在 Diesel 中针对 Postgres 数据库执行带子查询的删除?
How do I perform a delete with sub-query in Diesel against a Postgres database?
我在 Postgres 数据库中有以下模式:
Table A {
ID
Name
}
Table B {
ID FOREIGN KEY (A.ID)
}
我正在尝试在 Diesel 中编写以下查询:
DELETE FROM B
WHERE B.ID in (SELECT ID from A WHERE A.Name = $VAR)
$VAR
是我的应用程序传递的变量。
我第一次尝试写这篇文章是这样的:
fn deleteB(conn: &PgConnection, n: &str) {
use schema::A::dsl::*;
use schema::A;
use schema::B;
let res = A::table
.filter(Name.eq(n))
.select(ID);
.load(conn)
.unwrap();
assert!(res.len() < 2);
let b_id: i32 = *res.iter().nth(1).unwrap_or(&0);
let _rows = diesel::delete(
B::table
.filter(ID.eq(n_id))
)
.execute(conn)
.unwrap();
}
这可以编译,但它不起作用:ID 的 SELECT
语句总是 returns 0。它与 A 中插入的任何记录都不匹配,即使我手动检查了他们在那里。我确定我在匹配的方式上有错误(&str
vs &String
也许?),但我决定尝试不同的解决方案,因为我不喜欢这个,因为它必须对数据库执行两个单独的语句。
我的第二次尝试是这样的:
fn deleteB(conn: &PgConnection, n: &str) {
use schema::A::dsl::*;
use schema::A;
use schema::B;
let source = B::table.inner_join(A::table)
.filter(Name.eq(n));
let s = delete(source)
.execute(conn)
.unwrap();
}
对我来说这看起来更像 Diesel 惯用语(剧透警报,我几乎不了解框架)但果然,它无法编译:
|
410 | let s = delete(source)
| ^^^^^^ the trait `diesel::query_builder::IntoUpdateTarget` is not implemented for `diesel::query_builder::SelectStatement<diesel::query_source::joins::JoinOn<diesel::query_source::joins::Join<mobility2::schema::B::table...` (very long error)
当我意识到这似乎是一个微不足道的操作(删除本身)时,我正在研究上述特征,我可能最好寻求帮助。
如何正确编写惯用的 Diesel 代码来执行我想执行的删除语句?
由于 Diesel 语句直接映射到 SQL,您编写的查询将导致:
DELETE FROM TABLE B INNER JOIN TABLE A ON … WHERE name =
那是无效的 SQL,因此会导致编译时错误。
要获取您要编写的查询,您需要执行以下操作:
#[macro_use]
extern crate diesel;
use diesel::delete;
use diesel::prelude::*;
mod schema {
table! {
A(ID) {
ID -> Integer,
name -> Text,
}
}
table! {
B(ID) {
ID -> Integer,
}
}
allow_tables_to_appear_in_same_query!(A, B);
}
fn deleteB(conn: &PgConnection, n: &str) {
use schema::A;
use schema::B;
let s = delete(B::table)
.filter(B::ID.eq_any(A::table.filter(A::name.eq(n)).select(A::ID)))
.execute(conn)
.unwrap();
}
我在 Postgres 数据库中有以下模式:
Table A {
ID
Name
}
Table B {
ID FOREIGN KEY (A.ID)
}
我正在尝试在 Diesel 中编写以下查询:
DELETE FROM B
WHERE B.ID in (SELECT ID from A WHERE A.Name = $VAR)
$VAR
是我的应用程序传递的变量。
我第一次尝试写这篇文章是这样的:
fn deleteB(conn: &PgConnection, n: &str) {
use schema::A::dsl::*;
use schema::A;
use schema::B;
let res = A::table
.filter(Name.eq(n))
.select(ID);
.load(conn)
.unwrap();
assert!(res.len() < 2);
let b_id: i32 = *res.iter().nth(1).unwrap_or(&0);
let _rows = diesel::delete(
B::table
.filter(ID.eq(n_id))
)
.execute(conn)
.unwrap();
}
这可以编译,但它不起作用:ID 的 SELECT
语句总是 returns 0。它与 A 中插入的任何记录都不匹配,即使我手动检查了他们在那里。我确定我在匹配的方式上有错误(&str
vs &String
也许?),但我决定尝试不同的解决方案,因为我不喜欢这个,因为它必须对数据库执行两个单独的语句。
我的第二次尝试是这样的:
fn deleteB(conn: &PgConnection, n: &str) {
use schema::A::dsl::*;
use schema::A;
use schema::B;
let source = B::table.inner_join(A::table)
.filter(Name.eq(n));
let s = delete(source)
.execute(conn)
.unwrap();
}
对我来说这看起来更像 Diesel 惯用语(剧透警报,我几乎不了解框架)但果然,它无法编译:
|
410 | let s = delete(source)
| ^^^^^^ the trait `diesel::query_builder::IntoUpdateTarget` is not implemented for `diesel::query_builder::SelectStatement<diesel::query_source::joins::JoinOn<diesel::query_source::joins::Join<mobility2::schema::B::table...` (very long error)
当我意识到这似乎是一个微不足道的操作(删除本身)时,我正在研究上述特征,我可能最好寻求帮助。
如何正确编写惯用的 Diesel 代码来执行我想执行的删除语句?
由于 Diesel 语句直接映射到 SQL,您编写的查询将导致:
DELETE FROM TABLE B INNER JOIN TABLE A ON … WHERE name =
那是无效的 SQL,因此会导致编译时错误。
要获取您要编写的查询,您需要执行以下操作:
#[macro_use]
extern crate diesel;
use diesel::delete;
use diesel::prelude::*;
mod schema {
table! {
A(ID) {
ID -> Integer,
name -> Text,
}
}
table! {
B(ID) {
ID -> Integer,
}
}
allow_tables_to_appear_in_same_query!(A, B);
}
fn deleteB(conn: &PgConnection, n: &str) {
use schema::A;
use schema::B;
let s = delete(B::table)
.filter(B::ID.eq_any(A::table.filter(A::name.eq(n)).select(A::ID)))
.execute(conn)
.unwrap();
}