Laravel抱怨使用重复的命名参数进行查询

时间:2016-08-31 18:58:09

标签: php mysql sql laravel query-builder

当我这样做时(在laravel中):

<?php
\DB::select('SELECT * FROM my_table WHERE id = :id || id = :id', [
    'id' => 1,
]);

它说:

  

SQLSTATE [HY093]:参数号无效(SQL:SELECT * FROM my_table WHERE id =:id || id =:id)

但是当我这样做时(在纯PHP中):

<?php
$dbh = new PDO('mysql:dbname=...', '...', '...');
$stmt = $dbh->prepare('SELECT * FROM my_table WHERE id = :id || id = :id');
$r = $stmt->execute([
    'id' => 1,
]);
while ($row = $stmt->fetch()) {
    var_dump($row['id']);
}

成功了。我做错了什么?

P.S。显然,我遇到问题时遇到的查询更有意义。

UPD 或多或少的真实查询:

SELECT id
FROM objects
WHERE ACOS(
    SIN(RADIANS(lat)) * SIN(RADIANS(:lat))
    + COS(RADIANS(lat)) * COS(RADIANS(:lat)) * COS(RADIANS(:lng - lng))
) * 6371 < 10

2 个答案:

答案 0 :(得分:2)

从我所看到的一切都归结为mysql无法处理命名参数。

mysqli::prepare

  

此参数可以在SQL语句中包含一个或多个参数标记,方法是在适当的位置嵌入问号(?)字符。

pdo::prepare

  

在调用PDOStatement :: execute()时,必须为要传递给语句的每个值包含唯一的参数标记。除非启用了仿真模式,否则不能在预准备语句中多次使用同名的命名参数标记。

Laravel具有仿真模式disabled by default。可以通过将config/database.php添加到连接设置,在'options' => [PDO::ATTR_EMULATE_PREPARES => TRUE]中启用它。这样你就会得到与纯php相同的结果。但不确定这是个好主意。

答案 1 :(得分:0)

我通常使用带有“恒定”派生表(在FROM子句中的子查询)的CROSS JOIN解决。然后,我可以根据需要多次重复使用参数。

SELECT id
FROM objects o
CROSS JOIN (SELECT :lat as lat, :lng as lng) params
WHERE ACOS(
    SIN(RADIANS(o.lat)) * SIN(RADIANS(params.lat))
    + COS(RADIANS(o.lat)) * COS(RADIANS(params.lat)) * COS(RADIANS(params.lng - o.lng))
) * 6371 < 10