繁体   English   中英

MySQL 升级导致简单 WHERE 子句出现意外结果

[英]MySQL upgrade causing unexpected results on simple WHERE clauses

我正在将我的 Laravel 应用程序升级为使用 8.0.20 中的 MySQL 8.0.23,我发现 WHERE 子句存在问题,会产生意外结果。

SELECT * FROM guilds 
    WHERE platform_id = 1 
    AND platform_server_id = '407254666900930563';

直接在 MySQL 服务器上运行 ^ 会生成我要查找的记录(无论40725...int还是string )。 但是,通过 Laravel 的 Eloquent 查询生成器使用它,它没有找到记录。 这是 eloquent 代码。

// Won't find it if it's a string, will if it's an int
$serverId = '407254666900930563';
Server::where('platform_id', 1)
    ->where('platform_server_id', $serverId)
    ->first()

数据在这里:

在此处输入图像描述

我已经在数据库中验证platform_id确实 = 1(通过直接运行 SQL 验证)。

这是我在 Laravel 端的 MySQL 配置。

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
    PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
'modes'  => [
    /**
     * Disabled because of a group by we need
     */
    //'ONLY_FULL_GROUP_BY',

    'STRICT_TRANS_TABLES',
    'NO_ZERO_IN_DATE',
    'NO_ZERO_DATE',
    'ERROR_FOR_DIVISION_BY_ZERO',
    'NO_ENGINE_SUBSTITUTION',
]

我查看了 MySQL 条变更日志,但没有发现是什么原因造成的。 有没有人对我应该调查什么有任何想法?

CREATE TABLE 语句是:

CREATE TABLE `guilds` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `platform_id` bigint unsigned NOT NULL,
  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `platform_server_id` bigint unsigned NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `guilds_platform_id_platform_server_id_unique` (`platform_id`,`platform_server_id`),
  KEY `guilds_platform_server_id_index` (`platform_server_id`),
) ENGINE=InnoDB AUTO_INCREMENT=691420 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

我建议尝试两种方法,在这两种情况下我都建议您使用 where数组语法,因为它更灵活:

Model查询

Server::where([
  'platform_id'=> 1,
  'platform_server_id' => $serverId
])->first();

或者更明确的“哪里”

Server::where([
  ['platform_id', '=', 1],
  ['platform_server_id', '=', $serverId]
)->first();

数据库查询生成器

// table 'servers' or 'guilds', as I see above
DB::table('guilds')->where([
  'platform_id'=> 1,
  'platform_server_id' => $serverId
])->first();

或者更明确的“哪里”

// table 'servers' or 'guilds', as I see above
DB::table('guilds')->where([
  ['platform_id', '=', 1],
  ['platform_server_id', '=', $serverId]
])->first();

额外的建议

Mysql 变更日志

在这里,我找到了mysql 8.0.23 更新日志供您查看。

Laravel Tinker你可以使用命令php artisan tinker ,它允许你在终端中“编写纯”代码并执行它,你可以尝试我上面提到的查询,也可以尝试其他查询而不重构你的代码。

复制粘贴试试: Server::where([['platform_id', '=', 1],['platform_server_id', '=', 407254666900930563])->first();

这些看起来不一样:

407254666900930563

platform_server_id是 BIGINT 还是 VARCHAR?

另外,我看到引用值的不一致。

这是一个猜测:当 Laravel 运行不带引号的查询时,它会看到一个数字,并将其转换为DOUBLE 但是 Double 不能容纳超过 16 位有效数字。 您似乎需要全部 18 个。

请使用真实的数字——BIGINT 也有一个限制,即这些数字接近。

请提供SHOW CREATE TABLE ; 还有其他可能相关的细节。

几个月前,我们不得不将“doctrine/dbal”添加到 composer.json 中的“require”列表中,以修复一些奇怪的问题。 你可以通过运行这个来尝试:

composer require doctrine/dbal 

id 的声明和您使用的查询混淆了。 create table 语句中的 platform_server_id 是 bigint,但您尝试与字符串或您提到的 integer 进行比较:

`platform_server_id` bigint unsigned NOT NULL

$serverId = '407254666900930563';
Server::where('platform_id', 1)

如您在此答案中所见,您无法在不进行转换的情况下直接比较这些值: https://stackoverflow.com/a/72072468/7996624

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM