如何获取Laravel删除/更新/插入语句的原始SQL?

时间:2017-07-19 14:31:51

标签: php laravel eloquent

我知道我可以在查询构建器上使用toSql方法来获取带有SELECT语句的绑定参数占位符的原始SQL。

App\User::where(['id'=>'1'])->toSql();
"select * from `users` where (`id` = ?)"

但是如何才能获得DELETE声明呢?

App\User::where(['id'=>'1'])->delete()->toSql();
  

PHP错误:在第1行的整数上调用成员函数toSql()

这会执行语句,但是我希望得到原始的,未插入的SQL,其中的问号代表实际运行查询。同样的情况适用于任何修改语句,例如INSERTUPDATE

但为什么,谁在乎?

这闻起来很像xy problem。我的Web应用程序包括一个多进程架构。它运行自定义工匠命令,异步通信在事件驱动的循环中监听,以更新数据库。

我需要原始查询的原因是因为我想重用一个预准备语句以提高性能。不幸的是,雄辩的方法没有公开准备好的语句,所以为了重用它,我必须自己从底层的PDO连接中准备它。

$sql = 'UPDATE `foo` SET `bar` = ? WHERE (`id` = ?)';

$statement = DB::connection()->getPdo()->prepare($sql);

while (true) {
    $data = foo();
    $statement->execute([$data->bar, $data->id]);
}

然而,这与抽象的SQL语法构建器不同。因为我现在正在使用MySQL,所以我可以在语法上包含反引号。但现在我被供应商锁定了。比方说,老板说明天我们要转移到MS SQL Server,然后很可能会(至少)因为使用反引号而不是方括号来捕获错误。

我想使用动态生成的SQL语法在预准备语句中重用。

4 个答案:

答案 0 :(得分:5)

首先获取模型表的查询构建器实例。

$builder = DB::table((new User)->getTable());

然后获取语法并使用where子句从构建器编译delete语句。

$sql = $builder->getGrammar()->compileDelete($builder->where('id', 1));
"delete from `users` where `id` = ?"

现在,您可以自由地交换数据库驱动程序,并仍然可以获得适当的平台语法。

答案 1 :(得分:4)

您可以这样做:

DB::enableQueryLog();
App\User::where(['id'=>'1'])->delete();
dd(DB::getQueryLog());

答案 2 :(得分:1)

这就是我所做的。我在查询生成器上创建了一个toDeleteSql()宏。

\Illuminate\Database\Query\Builder::macro('toDeleteSql', function($func) {
    return [
        'sql' => $this->getGrammar()->compileDelete(with($this, $func)),
        'bindings' => $this->getBindings()
    ];
});

现在,当我查询时,我可以执行以下操作:

$user = \DB::table('user')
    ->toDeleteSql(function($query) {
        return $query
            ->join( 'photo', function($join) {
                $join->on('user.user_id', '=', 'photo.user_id');
                $join->where('photo.type','avatar');
            })
            ->where('user_id',123)
            ->whereNull('deleted_at');
    });

现在,用户是一个既包含SQL又包含绑定的数组,因此您可以使用它进行所需的操作。此外,您还可以在雄辩的查询生成器上创建宏以使用模型。

答案 3 :(得分:-2)

    -   id: flake8
        args: [--min-python-version, '3.6.1']
        additional_dependencies: [flake8-typing-imports==1.9.0]

像这样使用删除 $ deleted = DB :: delete('从用户中删除');

用于更新 $ affected = DB :: update('更新用户设置票数= 100,其中name =?',['John']);

参考 https://laravel.com/docs/5.8/database#running-queries