我有一个整数数组,需要作为一批行插入。每一行都需要一些其他数据。
$ids = [1,2]
$thing = 1
$now = Carbon::now(); // This is just a timestamp.
$binding_values = trim(str_repeat("({$thing}, ?, '{$now}'),", count($ids)), ',');
字符串$binding_values
如下所示:
“(1,?,'2019年1月1日00:00:00'),(1,?,'2019年1月1日00:00:00')”
然后我准备查询字符串并将参数绑定到它。使用IGNORE
是因为我在表上有一个复合唯一索引。但它似乎与问题无关,所以我省略了细节。
DB::insert("
INSERT IGNORE INTO table (thing, id, created_at)
VALUES {$binding_values}
", $ids);
这几乎总是有效的,但是我偶尔会得到一个错误SQLSTATE[HY000]: General error: 2031
。
我做这个参数的方式是否绑定了某种与Laravel的反模式?这个错误的来源可能是什么?
因为在这个方法中没有注入的风险,而且这个方法也不可能被扩展到有注入风险的用例,所以我修改了它,把所有的参数都烘焙进去,跳过参数绑定。到目前为止,我还没有看到任何错误。
我仍然想知道是什么原因导致了这种行为,这样我就可以在将来更好地处理它。我将感激任何见解。
1条答案
按热度按时间ct3nt3jp1#
我看不出您的查询有什么大问题,除了将参数烘焙到查询中,这容易受到SQL注入的攻击。
据我所知,您的问题是您需要
INSERT ÌGNORE INTO
,而Laravel不支持它。您是否考虑过使用staudenmeir/laravel-upsert这样的第三方软件包?另一种方法是将查询 Package 在事务中,并首先选择现有条目,这样就不必再次插入它们:
这样您只会插入尚未出现的内容,但您仍会保持在查询生成器的框架功能范围内。唯一的缺点是,由于需要第二次往返数据库,因此速度会稍慢。