打印1-1000质数并以&分隔报错:Data too long for column 'p'
问题分析与修复
你遇到的ERROR 1406本质是存储过程中拼接字符串的变量p长度不足,但核心诱因是质数判断逻辑错误,导致大量非质数被重复拼接到p中,让字符串长度迅速超出预设的varchar(2000)限制。
你的代码存在的具体问题:
- 质数判断时机错误:在内层
while n<=x的循环过程中,每次n递增后就判断y=2并执行拼接,但此时y还没统计完x的所有因数。比如x=4时,当n=2,y变为2,这时候错误地把4拼接到p里,但4的实际因数有1、2、4,最终y会是3,并非质数。这种错误会把大量非质数加入字符串,同时可能对同一个数多次拼接,导致p的长度急剧膨胀。 - 变量
p长度预留不足:即使逻辑正确,1000以内的质数有168个,用&分隔后总长度虽不到2000,但逻辑错误产生的冗余内容会轻易突破这个限制,建议改用更大的长度(比如varchar(10000))或text类型。 - 循环效率低下:内层循环从1开始且遍历到
x,做了大量无意义的判断(比如1是所有数的因数,无需单独统计)。
修复后的代码:
delimiter $$ create procedure a() begin declare x int default 3; declare n int default 2; -- 从2开始判断,跳过无意义的1 declare y int default 0; declare p varchar(10000) default '2'; -- 增大字符串长度 while x<=1000 do set y = 0; set n = 2; -- 优化:只需循环到sqrt(x),减少判断次数 while n <= sqrt(x) do if x % n = 0 then set y = 1; -- 找到因数,标记为非质数 leave; -- 直接退出内层循环,无需继续判断 end if; set n = n + 1; end while; -- 内层循环结束后确认是质数,再执行拼接 if y = 0 then set p = concat(p, '&', x); end if; set x = x + 1; end while; select p; end $$ call a();
关键修复说明:
- 调整拼接时机:将字符串拼接移到内层循环结束后,只有确认
x是质数时才执行拼接,避免错误添加非质数。 - 优化循环逻辑:内层循环从2开始,且只遍历到
sqrt(x),若x存在大于sqrt(x)的因数,必然对应一个小于sqrt(x)的因数,大幅减少循环次数。 - 扩大变量长度:将
p的类型改为varchar(10000),确保能容纳所有拼接内容,也可直接用text类型彻底避免长度限制问题。 - 移除冗余代码:原代码中的
case语句与外层while逻辑重复,直接保留while即可。
内容的提问来源于stack exchange,提问作者Ramya
相关产品推荐
相关产品推荐

