查询在 MySQL 中有效,但不能通过 Lumen/Laravel - 数值超出范围:1416
Posted
技术标签:
【中文标题】查询在 MySQL 中有效,但不能通过 Lumen/Laravel - 数值超出范围:1416【英文标题】:Query works in MySQL but not via Lumen/Laravel - Numeric value out of range: 1416 【发布时间】:2018-05-03 17:02:44 【问题描述】:我很难过... 很简单,我正在尝试更新 mysql 数据库中的几何记录,但由于某种原因,它失败了。但是,当 Lumen 抛出 QueryException
时,它会显示正在执行的查询;
UPDATE `user_locations` SET `current_location` = ST_GeomFromText('POINT(1 1)') WHERE user_id = 1
上述查询工作当我通过命令行在 MySQL 中执行它时,但由于某种原因,它不能通过 Laravel/Lumen/PDO/Eloquent 工作(不是确定是哪一个导致了问题)。
这是抛出的错误:
SQLSTATE[22003]: Numeric value out of range: 1416 Cannot get geometry object from data you send to the GEOMETRY field (SQL: update `user_locations` set `current_location` = ST_GeomFromText('POINT(1 1)') where `user_id` = 1)
我能想到的都试过了;
降级 MySQL(我看到其他人在使用 Mysql 5.7 时遇到类似问题) 直接从 Eloquent 转储查询和绑定,以查看实际发送到 MySQL 的内容(见下文) 更改数据库的引擎(目前是 InnoDB) 删除current_location
列上的空间索引
还有什么可能导致这种情况?它不能是 MySQL,因为它是通过命令行工作的,所以它肯定是 Laravel/Eloquent/PDO 中的东西?
其他信息
我正在运行 MySQL 5.7(我也尝试过 5.6,但它抛出了完全相同的错误) 我正在使用 Lumen,但我认为这无关紧要,因为 Laravel 和 Lumen 都使用 Eloquent 我正在使用https://github.com/grimzy/laravel-mysql-spatial,这(我相信)是相关代码: 更新 - 我认为这无关紧要,但在这个特定表上还有另一个point
字段,但由于我没有更新该字段,因此在查询中应该完全忽略它,因此,不相关...
Builder 扩展了 Illuminate\Database\Eloquent\Builder
/**
* Update a record in the database.
*
* @param array $values
* @return int
*/
public function update(array $values) : int
foreach ($values as $key => &$value)
if ($value instanceof GeometryInterface)
$value = $this->asWKT($value);
return parent::update($values);
/**
* Set the MySQL for the geometry field.
*
* @param GeometryInterface $geometry
* @return string
*/
protected function asWKT(GeometryInterface $geometry) : string
return $this->getQuery()->raw("ST_GeomFromText('" . $geometry->toWKT() . "')");
此外,我还尝试了以下方法:
Illuminate\Database\Query\Builder
public function update(array $values)
$sql = $this->grammar->compileUpdate($this, $values);
dd($sql, $values, $this->cleanBindings(
$this->grammar->prepareBindingsForUpdate($this->bindings, $values)
));
return $this->connection->update($sql, $this->cleanBindings(
$this->grammar->prepareBindingsForUpdate($this->bindings, $values)
));
这个输出:
string(70) "update `user_locations` set `current_location` = ? where `user_id` = ?"
array(1)
["current_location"]=>
&string(47) "ST_GeomFromText('POINT(1 1)')"
array(2)
[0]=>
&string(47) "ST_GeomFromText('POINT(1 1)')"
[1]=>
int(1)
【问题讨论】:
我希望这可能是解决方案:liquidweb.com/kb/how-to-disable-mysql-strict-mode 非常感谢@ThomasMoors,我会试试看 我认为使用DB::raw
来解决你的问题,看看这个 laracast 讨论:laracasts.com/discuss/channels/eloquent/…
感谢@teeyo,但这与$this->getQuery()->raw()
完全相同。可以肯定的是,我在 2 秒前尝试过,但不幸的是得到了相同的结果。
@teeyo 我收回(有点),我发现了这个问题,这是我最可悲、最令人恼火和完全荒谬的错误......见这里protected function asWKT(GeometryInterface $geometry) : string
。如果您能发现问题,请告诉我(我会尽快发布答案)
【参考方案1】:
看这里:
照亮\数据库\查询
/**
* Create a raw database expression.
*
* @param mixed $value
* @return \Illuminate\Database\Query\Expression
*/
public function raw($value)
return $this->connection->raw($value);
raw
的返回不是string
,而是\Illuminate\Database\Query\Expression
。因此,通过将 asWkt
的返回值转换为 string
,它会强制 Eloquent 用引号括起来,从而引发我们看到的错误。
【讨论】:
我注意到了,但不太确定这是错误的原因,很高兴你已经解决了 :)以上是关于查询在 MySQL 中有效,但不能通过 Lumen/Laravel - 数值超出范围:1416的主要内容,如果未能解决你的问题,请参考以下文章
mysql - 您不能在 FROM 子句中指定要更新的目标表(我的查询有效,但不是等效更新)
Laravel / Lumen formRequest 在提交所有有效值时抛出错误