PHP实现按owner_id递增pos列至60后重置为1的问题修正
问题:player_gift表pos字段更新异常,同一owner_id的pos值全部相同
需求说明
需要更新player.player_gift表的pos字段,规则为:每个owner_id对应的pos从1开始依次递增,当pos超过60时重置为1。但现有代码执行后,同一owner_id下的所有pos值完全相同,不符合预期。
问题代码
$st = $dbh->query("SELECT * from player.player_gift"); $test = $st->fetchAll(); if(isset($_POST['pregatit'])) { foreach($test as $test2) { if(!is_null($test2['owner_id'])) { $st = $dbh->prepare('UPDATE player.player_gift SET pos = ? WHERE owner_id = ?'); $st->execute([getRandomPositionFor($test2['owner_id']), $test2['owner_id']]); } else { // wh_log('id ul' . $test2['owner_id'] . 'a dat eroare'); } } die(); } function getRandomPositionFor($ownerid) { static $lastposinserted = 0; static $lastownerid = -1; $lastownerid = $ownerid; if($lastownerid != $ownerid) $lastposinserted = 0; if($lastposinserted > 60) $lastposinserted = 0; $lastposinserted++; return $lastposinserted; }
当前执行结果
| owner_id | pos |
|---|---|
| 204412 | 19 |
| 204412 | 19 |
| 204412 | 19 |
| 204405 | 24 |
| 204405 | 24 |
| 204405 | 24 |
| 204405 | 24 |
| 204390 | 48 |
| 204390 | 48 |
| 204390 | 48 |
期望结果
| owner_id | pos |
|---|---|
| 204412 | 1 |
| 204412 | 2 |
| 204412 | 3 |
| 204405 | 1 |
| 204405 | 2 |
| 204405 | 3 |
| 204405 | 4 |
| 204390 | 1 |
| 204390 | 2 |
| 204390 | 3 |
问题分析
- 函数逻辑错误:
getRandomPositionFor函数中,先将$lastownerid赋值为当前$ownerid,再判断$lastownerid != $ownerid,这个判断永远不成立,导致切换owner_id时无法重置计数器。 - UPDATE条件错误:仅用
owner_id作为WHERE条件,每次循环执行UPDATE都会覆盖该owner_id下的所有记录,最终所有记录都是最后一次调用函数返回的数值。 - 计数器未按owner_id隔离:全局静态变量
$lastposinserted无法为每个owner_id独立维护递增计数,导致不同owner_id的计数混在一起。
修复后的代码
if(isset($_POST['pregatit'])) { // 按owner_id分组查询,确保同一owner_id的记录连续处理 $st = $dbh->query("SELECT * from player.player_gift ORDER BY owner_id"); $test = $st->fetchAll(); // 用数组维护每个owner_id的当前pos计数 $ownerPosCounts = []; foreach($test as $test2) { $ownerId = $test2['owner_id']; if(is_null($ownerId)) { // wh_log('id ul' . $ownerId . 'a dat eroare'); continue; } // 初始化当前owner_id的计数 if(!isset($ownerPosCounts[$ownerId])) { $ownerPosCounts[$ownerId] = 0; } // 递增计数,超过60重置为1 $ownerPosCounts[$ownerId]++; if($ownerPosCounts[$ownerId] > 60) { $ownerPosCounts[$ownerId] = 1; } // 使用唯一主键(假设表中有id字段)更新单条记录,避免批量覆盖 $st = $dbh->prepare('UPDATE player.player_gift SET pos = ? WHERE id = ?'); $st->execute([$ownerPosCounts[$ownerId], $test2['id']]); } die(); }
修复说明
- 按
owner_id排序查询,保证同一owner_id的记录连续处理。 - 用数组
$ownerPosCounts为每个owner_id独立维护pos计数器,避免全局变量的混乱。 - UPDATE语句使用记录的唯一主键(如
id)作为WHERE条件,确保每次只更新单条记录,实现逐个递增。
内容的提问来源于stack exchange,提问作者Filip. Filip.
相关产品推荐
相关产品推荐

