【问题标题】:MySQL Error 1157 while updating, however i'm using the primary key in the where clauseMySQL 更新时出现错误 1157,但是我在 where 子句中使用主键
【发布时间】:2019-10-23 11:29:37
【问题描述】:

我收到 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 子句中使用了 Primary 键?

【问题讨论】:

  • 只是一个猜测 - 也许BINARY 关键字被认为是一个函数,因此 WHERE 子句不直接使用主键,而是使用从主键派生的一组值。
  • @schtever 嗯,谢谢,有道理

标签: mysql


【解决方案1】:

仅使用键列是不够的,您必须以允许使用索引来查找行的方式使用它。来自documentation

如果优化器决定不使用键列上的索引,即使在 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);

【讨论】:

    【解决方案2】:

    您可以在更新查询之前添加SET SQL_SAFE_UPDATES=0;。使用时要小心,因为它可能会进行意外的数据修改。

    或者您可以尝试在 where 子句中包含 ip_countryCode 列。

    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') AND ip_countryCode <> 'GB';
    

    或者您可以删除 BINARY 函数

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

    【讨论】:

    • 谢谢,但我希望我能知道这种行为的原因。
    • 安全更新模式默认开启。这可以防止意外覆盖大量数据。使用SET SQL_SAFE_UPDATES=0; 意味着您知道自己在做什么,即更新所有指定范围的 IP 地址。
    • 我的意思是“尽管我在 where 子句中使用了主键,但为什么会触发此错误”?
    • 这是因为 BINARY 函数。如果您删除 BINARY 函数,那么它应该可以在没有 AND ip_countryCode &lt;&gt; 'GB'; 的情况下正常工作
    猜你喜欢
    • 1970-01-01
    • 2018-03-21
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-01
    • 2020-12-13
    相关资源
    最近更新 更多