deleteAll 有条件和删除限制

deleteAll with conditions and a delete limit

蛋糕PHP版本:4.2.6

Xampp:
Apache/2.4.51 (Win64) OpenSSL/1.1.1l PHP/8.0.11
服务器版本:10.4.21-MariaDB - mariadb.org 二进制分发
PHP版本:8.0.11

简介

我正在尝试使用 order by 和 limit 子句构建 deleteAll 查询。

SQL

当下面的 sql 在 xampp sql 选项卡 window 中是 运行 时,它只会按正确的顺序删除一行,这就是我想要它做。

DELETE FROM `report_dashs` ORDER BY `id` ASC LIMIT 1;

API 文档

我想使用带条件的 deleteAll 来复制它。我在 api 中引用了 this 文档:

deleteAll(混合$条件)

参数 混合$条件 要使用的条件,接受任何 Query::where() 可以接受的东西。

Returns 整数 Returns 受影响的行数。

我试过的

在此基础上,我构建了以下查询:

$this->ReportDashs->deleteAll(
    [
        'user_id' => 1001
    ])
    ->order(['id' => 'DESC'])
    ->limit(1);

这会引发错误:

调用 int 上的成员函数 order()

这一行->order(['id' => 'DESC'])

并删除所有 returns 一个整数。

总结

我已经尝试了很多配置,但每次尝试要么引发语法错误,要么被删除 所有行。调试工具包 sql 日志总是缺少 order 和 limit 子句。

问题

如何构造 deleteAll 查询并遵守 order by 和 limit 子句。

备注

如果完整的堆栈跟踪有助于让我知道,我会 post 它。

谢谢, 曾兹.


解决方案

尝试预先加载和自定义查找器:

// 控制器:

$query = $this->ReportDashs->find('clearSuperuserData', [
    'contain' => ['Users'],
    'client_id' => 1234
])
->delete()
->epilog('ORDER BY id ASC LIMIT 1')
->execute();

// 查找器:

public function findClearSuperuserData(Query $query, array $options): object
{
    $query
        ->where(['Users.client_id' => $options['client_id']]);
    return $query;
}

但是用户 table 从未在 where 子句中得到尊重。

尝试不预先加载和自定义查找器:

$query = $this->ReportDashs
    ->find()
    ->where(['user_id' => 1003])
    ->delete()
    ->epilog('ORDER BY id ASC LIMIT 1')
    ->execute();

这会按应用限制的顺序删除正确的行。

检查 API 文档中的 Table::deleteAll(),这是删除所有符合给定条件的记录的便捷方法,它将 return 受影响的行数。

对于更复杂的查询,您通常可以使用查询构建器,但是目前 ORDERLIMIT 不支持 UPDATEDELETE 查询。 The last attempt to implement it 以 cross-DBMS 的方式不幸被放弃了。

目前您可以使用完全原始的 SQL,或者在您的特定情况下 MariaDB/MySQL,您可以使用查询生成器的结尾附加 ORDERLIMIT 条款:

$query = $this->ReportDashs
    ->query()
    ->delete()
    ->epilog('ORDER BY id ASC LIMIT 1');

$query = $this->ReportDashs
    ->query()
    ->delete()
    ->epilog(
        $this->ReportDashs
            ->getConnection()
            ->newQuery()
            ->orderDesc('id')
            ->limit(1)
    );

两者都会产生

DELETE FROM report_dashs ORDER BY id DESC LIMIT 1

后者支持自动标识符引用。

或者,如果您喜欢冒险,您可以创建一个扩展查询编译器来编译所需的子句,\Cake\Database\QueryCompiler::$_deleteParts 需要修改以包含 orderlimit部分。