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

Discuz环境PHP生成随机排名写入t2_rank出现数据重复排查

问题分析

你的代码存在以下5个核心问题,直接导致数据重复写入、批次缺失:

  • foreach循环变量引用错误:遍历t1_user结果集时你使用了未定义的$id变量,没有读取当前行的用户ID$su['id']。如果运行环境存在全局$id变量刚好从1递增到1000后重置,就会出现前1000条ID正常、后续从头重复的现象。
  • array_slice参数使用错误:array_slice第三个参数是截取长度不是结束下标,你每次循环累加$tpp导致截取长度越来越大,会出现重复截取、批次数据错乱的问题,正确长度应该固定为500。
  • 循环边界错误:总批次$runningtime计算完成后,你用$y < $runningtime作为循环条件,会少执行最后一批写入:比如5400条数据需要11批次,你的代码只会执行10次,漏掉最后400条。
  • 数组下标不匹配:你给$newdata赋值时下标从1开始,而array_slice默认按0起始的偏移量计算,容易出现数据错位问题。
  • SQL插入字段缺失:t2_rank表存在name字段,但你的REPLACE INTO语句只插入了rank和id两个字段,如果name字段没有设置外键自动同步或默认值,也会导致字段数据异常。
修复后代码
$checkfirst = DB::result_first("SELECT count(*) cnt FROM ".DB::table('t2_rank'));
if($checkfirst == 0){
    // 仅读取需要的字段减少内存占用
    $s = DB::fetch_all("SELECT id,name FROM ".DB::table('t1_user')." ORDER BY RAND()");
    $newdata = [];
    $total = count($s);
    foreach($s as $k => $su){
        $rank = $k + 1;
        // 字符串转义避免SQL注入
        $name = addslashes($su['name']);
        $newdata[] = "($rank, {$su['id']}, '$name')";
    }
        
    $pagesplit = 500; // 每批写入500条
    $runningtime = ceil($total / $pagesplit);      

    for($y=0; $y < $runningtime; $y++){
        $offset = $y * $pagesplit;
        // 固定截取长度为500,不足时自动取到数组末尾
        $genewdata = array_slice($newdata, $offset, $pagesplit);
        $tobeupdate = implode(',', $genewdata);
        DB::query("REPLACE INTO ".DB::table('t2_rank')." (rank,id,name) VALUES ".$tobeupdate);
    }
}

如果你t2_rank的name字段已经通过外键关联t1_user自动同步,可以省略插入name字段,对应调整SQL的字段和值部分即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 11:51:03