我具有导出功能,我想使用给定的ID查询和导出。我找到了一种使用skip()
和take()
进行查询的解决方案,但是现在whereIn('id', $ids)
给我错误,因为到目前为止它有85,000条记录。
PDOException:SQLSTATE [HY000]:常规错误:1390准备好的语句包含太多占位符
我使用的解决方案是:
public function handle() {
$max = 5000;
$total = $this->givenIds->count();
$pages = ceil($total / $max);
for ($i = 1; $i < ($pages + 1); $i++) {
$offset = (($i - 1) * $max);
$start = ($offset == 0 ? 0 : ($offset + 1));
MyModel::whereIn('id', $givenIds)
->orderBy('created_at', 'desc')
->skip($start)
->take($max)
->get();
// $this->generateTempCsv();
}
// $this->combineTempCSVs()
}
在没有瓶颈的情况下,它运行良好,直到出现过多的占位符错误为止。现在,我收到此错误,我尝试:
$query = MyModel::orderBy('created_at', 'desc')
foreach ($this->givenIds->chunk(2000) as $i => $chunk) {
if ($i == 0) {
$query = $query->whereIn('id', $chunk);
} else {
$query = $query->orWhereIn('id', $chunk);
}
}
这给出了相同的错误。
如果我想使用给定的ID进行查询,并且仍然想保留“ orderBy-created_at”而不会出现瓶颈,该怎么办?
givenIds来自控制器(上面的代码是Job):
$givenIds = MyModel::select('id', 'created_at')
->where(function($q) use ($dateRange, $queries) {
$this->applyQueryFilters($q, $queries, $dateRange);
})
->orderBy('created_at', 'desc')
->pluck('id');
Exporter::dispatch($givenIds)->onQueue('export');
PS:之所以使用$givenIds
是因为有过滤器,首先在应用过滤器后将$givenIds
传递到工作中,然后获得了相关的ID。在获取$givenIds
并从那里开始排序时,我是否需要按ID排序?
答案 0 :(得分:1)
尝试以下操作:在数据库配置文件中的sql
下或用于连接数据库的驱动程序中,添加如下字段options
'options'=> [PDO::ATTR_EMULATE_PREPARES => true]
PHP API实际上(check this):
某些驱动程序不支持本机预处理语句或对此的支持有限。
另一种解决方案应该是更改驱动程序,但我想在database.php中添加一行更容易
可能的副作用报告::这可能会将返回值强制转换为字符串,如果您使用===
作为比较运算符,则会影响您的代码。您可以使用模型中的protected $casts
变量解决此问题(如果您使用的是Laravel)