我知道我可以在查询构建器上使用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,其中的问号代表而实际运行查询。同样的情况适用于任何修改语句,例如INSERT
或UPDATE
这闻起来很像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语法在预准备语句中重用。
答案 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']);