首页 > 解决方案 > MySQL 更新时出现错误 1157,但是我在 where 子句中使用主键

问题描述

我收到 1157 错误

错误代码:1175。您正在使用安全更新模式,并且您尝试更新没有使用 KEY 列的 WHERE 的表。要禁用安全模式,请切换 Preferences -> SQL Editor 中的选项并重新连接。

当我尝试执行此语句时

UPDATE ip 
SET 
    ip_countryCode = 'GB',
    ip_countryName = 'United Kingdom',
    ip_city = 'London' 

WHERE BINARY ip_ip >= INET6_ATON('2.57.77.0') AND 
      BINARY ip_ip <= INET6_ATON('2.57.77.255');

这是表的创建ip

CREATE TABLE `ip` (
  `ip_ip` varbinary(16) NOT NULL,
  `ip_last_request_time` timestamp(3) NULL DEFAULT NULL,
  `ip_city` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT '',
  `ip_countryCode` varchar(3) COLLATE utf8mb4_unicode_ci DEFAULT '',
  `ip_countryName` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT '',
/*
more 23 columns have been omitted for readability
*/
  PRIMARY KEY (`ip_ip`),
  KEY `countryCode_index` (`ip_countryCode`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

我在这里做错了什么?为什么我收到此错误,但是在 where 子句中使用了键?

标签: mysql

解决方案


仅使用键列是不够的,您必须以允许使用索引来查找行的方式使用它。从文档中:

如果优化器决定不使用键列上的索引,即使使用 WHERE 子句中指定的键,UPDATE 和 DELETE 语句也可能在安全更新模式下产生错误。

由于您正在测试的值BINARY ip_ip而不仅仅是ip_ip它本身,因此它不能使用索引,因此您会收到错误消息。

您可以使用函数将结果转换INET6_ATON()varbinary,而不是使用BINARY列上的运算符吗?然后它应该能够使用索引并且您不会收到错误。

UPDATE ip 
SET 
    ip_countryCode = 'GB',
    ip_countryName = 'United Kingdom',
    ip_city = 'London' 

WHERE ip_ip BETWEEN CAST(INET6_ATON('2.57.77.0') AS BINARY(16)) AND 
                    CAST(INET6_ATON('2.57.77.255') AS BINARY(16);

推荐阅读