问题
When I do (in laravel):
<?php
\DB::select('SELECT * FROM my_table WHERE id = :id || id = :id', [
'id' => 1,
]);
It says:
SQLSTATE[HY093]: Invalid parameter number (SQL: SELECT * FROM my_table WHERE id = :id || id = :id)
But when I do (in pure 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']);
}
It succeeds. What am I doing wrong?
P.S. Apparently, the query I ran when I encountered the issue was more meaningful.
UPD More or less real query:
SELECT id
FROM objects
WHERE ACOS(
SIN(RADIANS(lat)) * SIN(RADIANS(:lat))
+ COS(RADIANS(lat)) * COS(RADIANS(:lat)) * COS(RADIANS(:lng - lng))
) * 6371 < 10
回答1:
From what I can see it all comes down to mysql
being unable to deal with named parameters.
mysqli::prepare:
This parameter can include one or more parameter markers in the SQL statement by embedding question mark (?) characters at the appropriate positions.
pdo::prepare:
You must include a unique parameter marker for each value you wish to pass in to the statement when you call PDOStatement::execute(). You cannot use a named parameter marker of the same name more than once in a prepared statement, unless emulation mode is on.
Laravel has emulation mode disabled by default. One can enable it in config/database.php
by adding 'options' => [PDO::ATTR_EMULATE_PREPARES => TRUE]
to connection settings. That way you will get the same result as in pure php. Not sure that's a good idea, though.
回答2:
I usually solve that using a CROSS JOIN with a "constant" derived table (subquery in FROM clause). Then I can reuse the parameters as many times as I want.
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
来源:https://stackoverflow.com/questions/39257070/laravel-complains-about-query-with-duplicate-named-parameters