You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL WHERE子句比较年份触发BIGINT UNSIGNED溢出如何解决

问题描述

我有一张名为links的表,用于关联父子两类分类,该表共有5个字段:

  • autoinc
  • parent_category_name year(4) NOT NULL
  • parent_category_year varchar(255) NOT NULL
  • child_category_name year(4) NOT NULL
  • child_category_year varchar(255) NOT NULL

我需要编写INSERT SELECT语句查询获取父子分类的category_id,将其插入临时表,编写的初始查询语句如下:

INSERT INTO temp (parent_category_id, child_category_id)
SELECT parent.parent_category_id, child.child_category_id
  FROM links
  JOIN categories AS parent
       ON   parent.name = link.parent_category_name
       AND  parent.year = link.parent_category_year
  JOIN categories AS child
       ON   child.name = link.child_category_name
       AND  child.year = link.child_category_year

该查询运行正常,但我需要新增以下业务规则:

  • 父分类年份与子分类年份相等
    或
  • 父分类年份比子分类年份小1

我为查询新增了如下WHERE子句:

WHERE link.child_category_year = link.parent_category_year
   OR link.child_category_year - link.parent_category_year = 1 

但该INSERT语句在Perl代码中执行时抛出如下异常:

DBI Exception: DBD::mysql::db do failed: BIGINT UNSIGNED value is out of range in '(`my_database`.`links`.`child_category_year` - `my_database`.`links`.`parent_category_year`)' [for Statement "
原因分析

报错的核心原因是年份字段为*无符号整数(UNSIGNED)*类型,当父分类年份大于子分类年份时,child_category_year - parent_category_year的运算结果为负数,无符号类型无法存储负数,就会触发数值溢出报错。

解决方案

这里提供两种可行方案,优先推荐第二种,无需类型转换、性能更高:

方案1:将字段转为有符号整数后运算

通过CAST函数将无符号的年份字段转为有符号整数,再做减法运算,避免溢出:

WHERE link.child_category_year = link.parent_category_year
   OR CAST(link.child_category_year AS SIGNED) - CAST(link.parent_category_year AS SIGNED) = 1

方案2:调整判断逻辑,完全避免减法运算

将「子年份减父年份等于1」的判断等价转换为「子年份等于父年份加1」,从根源上避免出现负数运算,性能更优:

WHERE link.child_category_year = link.parent_category_year
   OR link.child_category_year = link.parent_category_year + 1

内容的提问来源于stack exchange,提问作者ComputersAreNeat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 15:18:03