SQL 使用 Laravel Eloquent 和命名绑定进行查询:混合命名参数和位置参数
SQL query with Laravel Eloquent and named bindings : mixed named and positional parameters
我正在尝试执行以下查询。请注意,我必须在此查询中使用 命名参数 。
我不明白这个问题,因为我似乎只使用命名参数。如何使命名参数起作用?
Note : the query is fully functionnal when I'm executing it in DB or in laravel with a simple DB::table(users)->select( $sql_with_values_inside )
我是 Laravel 的新手,所以也许我做错了。
查询
$latitude = (float)$latitude;
$longitude = (float)$longitude;
$radius = (float)$radius;
$sql = '`firstname`,`lastname`,`email`,
ST_X(`coordinates_public`) AS latitude,
ST_Y(`coordinates_public`) AS longitude,
(6371 * ACOS(COS(RADIANS(:latitude)) * COS(RADIANS(ST_Y(coordinates_private))) * COS(RADIANS(ST_X(coordinates_private)) - RADIANS(:longitude)) + SIN(RADIANS(:latitude)) * SIN(RADIANS(ST_Y(coordinates_private))))) AS distance';
$washers = DB::table('users')
->selectRaw($sql, ['latitude' => $latitude,'longitude'=> $longitude,'radius'=> $radius])
->whereRaw('MBRContains ( LineString (
Point (
:longitude + :radius / (111.320 * COS(RADIANS(:latitude))),
:latitude + :radius / 111.133
),
Point (
:longitude - :radius / (111.320 * COS(RADIANS(:latitude))),
:latitude - :radius / 111.133
)), `coordinates_private`
)', ['latitude' => $latitude,'longitude'=> $longitude,'radius'=> $radius])
->having('distance < :radius', ['radius'=> $radius])
->orderBy('distance')
->get();
错误
Illuminate\Database\QueryException: SQLSTATE[HY093]:
Invalid parameter number: mixed named and positional parameters (SQL: select `firstname`,`lastname`,`email`,
ST_X(`coordinates_public`) AS latitude,
ST_Y(`coordinates_public`) AS longitude,
(6371 * ACOS(COS(RADIANS(:latitude)) * COS(RADIANS(ST_Y(coordinates_private))) * COS(RADIANS(ST_X(coordinates_private)) - RADIANS(:longitude)) + SIN(RADIANS(:latitude)) * SIN(RADIANS(ST_Y(coordinates_private))))) AS distance from `users` where MBRContains (
LineString
(
Point (
:longitude + :radius / (111.320 * COS(RADIANS(:latitude))),
:latitude + :radius / 111.133
),
Point (
:longitude - :radius / (111.320 * COS(RADIANS(:latitude))),
:latitude - :radius / 111.133
)
),
`coordinates_private`) having `distance < :radius` = 4.8312518210935 order by `distance` asc)
我不确定这是否是问题所在,但据我所知您不能多次使用相同的参数名称,例如对于这部分查询:
:longitude + :radius / (111.320 * COS(RADIANS(:latitude))),
你应该使用:
:longitude + :radius / (111.320 * COS(RADIANS(:latitude2))),
然后传递3个参数:
['latitude' => $latitude,'longitude'=> $longitude, 'latitude2' => $latitude]
当然,对于查询的其他部分,您应该尝试同样的事情。请记住,我对此不是 100% 确定,因为我很少使用命名参数。
在 select 中您没有 :radius
但尝试绑定它。
应该是
->selectRaw($sql, ['latitude' => $latitude,'longitude'=> $longitude])
来自 PHP 手册:
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.
因此您不能使用同名的命名参数标记。
有两种解决方案:
- 对相同的值使用不同的命名绑定键:
$sql = "(6371 * ACOS(COS(RADIANS(:lat)) * COS(RADIANS(ST_Y(coordinates_private))) * COS(RADIANS(ST_X(coordinates_private)) - RADIANS(:long)) + SIN(RADIANS(lat2)) * SIN(RADIANS(ST_Y(coordinates_private))))) AS distance";
...
->selectRaw($sql, ["lat" => $latitude, "long" => $longitude, "lat2" => $latitude])
- 使用
?
代替命名绑定和绑定数组:
$sql = '(6371 * ACOS(COS(RADIANS(?)) * COS(RADIANS(ST_Y(coordinates_private))) * COS(RADIANS(ST_X(coordinates_private)) - RADIANS(?)) + SIN(RADIANS(?)) * SIN(RADIANS(ST_Y(coordinates_private))))) AS distance';
...
->selectRaw($sql, [$latitude, $longitude, $latitude])
我正在尝试执行以下查询。请注意,我必须在此查询中使用 命名参数 。 我不明白这个问题,因为我似乎只使用命名参数。如何使命名参数起作用?
Note : the query is fully functionnal when I'm executing it in DB or in laravel with a simple DB::table(users)->select( $sql_with_values_inside )
我是 Laravel 的新手,所以也许我做错了。
查询
$latitude = (float)$latitude;
$longitude = (float)$longitude;
$radius = (float)$radius;
$sql = '`firstname`,`lastname`,`email`,
ST_X(`coordinates_public`) AS latitude,
ST_Y(`coordinates_public`) AS longitude,
(6371 * ACOS(COS(RADIANS(:latitude)) * COS(RADIANS(ST_Y(coordinates_private))) * COS(RADIANS(ST_X(coordinates_private)) - RADIANS(:longitude)) + SIN(RADIANS(:latitude)) * SIN(RADIANS(ST_Y(coordinates_private))))) AS distance';
$washers = DB::table('users')
->selectRaw($sql, ['latitude' => $latitude,'longitude'=> $longitude,'radius'=> $radius])
->whereRaw('MBRContains ( LineString (
Point (
:longitude + :radius / (111.320 * COS(RADIANS(:latitude))),
:latitude + :radius / 111.133
),
Point (
:longitude - :radius / (111.320 * COS(RADIANS(:latitude))),
:latitude - :radius / 111.133
)), `coordinates_private`
)', ['latitude' => $latitude,'longitude'=> $longitude,'radius'=> $radius])
->having('distance < :radius', ['radius'=> $radius])
->orderBy('distance')
->get();
错误
Illuminate\Database\QueryException: SQLSTATE[HY093]:
Invalid parameter number: mixed named and positional parameters (SQL: select `firstname`,`lastname`,`email`,
ST_X(`coordinates_public`) AS latitude,
ST_Y(`coordinates_public`) AS longitude,
(6371 * ACOS(COS(RADIANS(:latitude)) * COS(RADIANS(ST_Y(coordinates_private))) * COS(RADIANS(ST_X(coordinates_private)) - RADIANS(:longitude)) + SIN(RADIANS(:latitude)) * SIN(RADIANS(ST_Y(coordinates_private))))) AS distance from `users` where MBRContains (
LineString
(
Point (
:longitude + :radius / (111.320 * COS(RADIANS(:latitude))),
:latitude + :radius / 111.133
),
Point (
:longitude - :radius / (111.320 * COS(RADIANS(:latitude))),
:latitude - :radius / 111.133
)
),
`coordinates_private`) having `distance < :radius` = 4.8312518210935 order by `distance` asc)
我不确定这是否是问题所在,但据我所知您不能多次使用相同的参数名称,例如对于这部分查询:
:longitude + :radius / (111.320 * COS(RADIANS(:latitude))),
你应该使用:
:longitude + :radius / (111.320 * COS(RADIANS(:latitude2))),
然后传递3个参数:
['latitude' => $latitude,'longitude'=> $longitude, 'latitude2' => $latitude]
当然,对于查询的其他部分,您应该尝试同样的事情。请记住,我对此不是 100% 确定,因为我很少使用命名参数。
在 select 中您没有 :radius
但尝试绑定它。
应该是
->selectRaw($sql, ['latitude' => $latitude,'longitude'=> $longitude])
来自 PHP 手册:
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.
因此您不能使用同名的命名参数标记。
有两种解决方案:
- 对相同的值使用不同的命名绑定键:
$sql = "(6371 * ACOS(COS(RADIANS(:lat)) * COS(RADIANS(ST_Y(coordinates_private))) * COS(RADIANS(ST_X(coordinates_private)) - RADIANS(:long)) + SIN(RADIANS(lat2)) * SIN(RADIANS(ST_Y(coordinates_private))))) AS distance";
...
->selectRaw($sql, ["lat" => $latitude, "long" => $longitude, "lat2" => $latitude])
- 使用
?
代替命名绑定和绑定数组:
$sql = '(6371 * ACOS(COS(RADIANS(?)) * COS(RADIANS(ST_Y(coordinates_private))) * COS(RADIANS(ST_X(coordinates_private)) - RADIANS(?)) + SIN(RADIANS(?)) * SIN(RADIANS(ST_Y(coordinates_private))))) AS distance';
...
->selectRaw($sql, [$latitude, $longitude, $latitude])