当我这样做时(在laravel中):
<?php \DB::select('SELECT * FROM my_table WHERE id = :id || id = :id', [ 'id' => 1, ]);
它说:
SQLSTATE [HY093]:无效的参数号(SQL:SELECT * FROM my_table,其中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']); }
成功了。我究竟做错了什么?
PS显然,遇到问题时我运行的查询更有意义。
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
从我所看到的一切都可以归结为mysql无法处理命名参数。
mysql
mysqli::prepare:
mysqli::prepare
通过在适当位置嵌入问号(?)字符,此参数可以在SQL语句中包括一个或多个参数标记。
pdo::prepare:
pdo::prepare
调用PDOStatement :: execute()时,对于要传递给语句的每个值,必须包含一个唯一的参数标记。除非打开了仿真模式,否则在准备好的语句中不能多次使用相同名称的命名参数标记。
Laravel默认禁用 仿真模式。可以通过添加连接设置来启用它。这样,您将获得与纯PHP相同的结果。不过,不确定这是个好主意。config/database.php``'options' => [PDO::ATTR_EMULATE_PREPARES => TRUE]
config/database.php``'options' => [PDO::ATTR_EMULATE_PREPARES => TRUE]