PHP自动删除标识字符串中所需的零

PHP自动删除标识字符串中所需的零,php,mysql,Php,Mysql,在表中,主字段是名为ribiid的Char(12)字段,其格式为RB 它需要自动递增,为此我准备了以下代码: function getid() { global $connection; $idquery = "SELECT ribiid FROM systems ORDER BY ribiid DESC LIMIT 1"; $idsave = mysqli_query($connection, $idquery); $idresult = mysqli_fetch_as

在表中,主字段是名为
ribiid
的Char(12)字段,其格式为
RB

它需要自动递增,为此我准备了以下代码:

function getid() {
   global $connection;
   $idquery = "SELECT ribiid FROM systems ORDER BY ribiid DESC LIMIT 1";
   $idsave = mysqli_query($connection, $idquery);
   $idresult = mysqli_fetch_assoc($idsave);
   $idalpha = substr($idresult['ribiid'], 0, 2);
   $idnumeric = substr($idresult, 2);
   $newidnumeric = $idnumeric + 1;
   $newid = $idalpha . $newidnumeric;
   return $newid;
}
现在,为了进行测试,我在cmd中手动输入了一行
id=RB0000000000
,我使用php通过网页提交的下一个条目应该是
RB0000000001
,但它是RB1


这是我的第一个web数据库,我如何修复它。谢谢

您可以尝试以下方式:

$newid = $idalpha . str_pad($newidnumeric, 10, '0', STR_PAD_LEFT);

这将添加0以达到十个字符。

您的问题是,当向
$idnumeric
添加1时,PHP需要将其视为一个数字。数字中的前导零没有意义,因此它们被丢弃

要保留零,您可以使用
sprintf
格式化生成的(递增的)数字:

然而,使用这样的代码并不是一个好主意 不过,这段代码有一个问题:它受到种族条件的制约。考虑如果脚本的两个实例并行运行会发生什么:

                Instance A                    Instance B
T  |
i  |            Reads ribiid RB..001          Reads ribiid RB..001
m  |            Generates next id RB..002     Generates next id RB..002
e  v            Writes RB..002 to DB
                                              Writes RB..002 to DB => OOPS
如您所见,由于使用了重复的主键,这种情况将导致实例B无法插入记录。要解决此问题,您需要消除竞态条件,您可以通过以下几种方式之一实现:

  • 对PK使用
    AUTO_INCREMENT
    列,而不是手动插入值。虽然这意味着您不能再将“RB”前缀作为键的一部分,但您可以将其移动到另一列,并使PK成为这两列的组合
  • LOCK TABLES ribiid
    插入时(请注意,锁定需要覆盖整个过程,而不仅仅是
    getid
    函数)。锁定表通常是您希望避免的,但如果插入不频繁,这是一个实用的解决方案

您可以使用以下功能再次填充数字字符串:

function pad_number($number, $pad=10){
  $pad_zero = $pad - strlen($number.'');
  $nstr = '';
  for($i =0; $i< $pad_zero; $i++){
    $nstr .="0";
  }
  $nstr .= $number;
  return $nstr;
}

您应该使用MySQL的功能,而不是试图在PHP中实现类似的功能(如果您不非常小心,这将导致种族危险)。是的,使用自动增量,然后当您希望使用您的格式时,使用带字符串前缀的
sprintf
。谢谢。你能解释一下什么是种族危险吗?@user3324298,种族危险是指当你有多个写操作,并且你希望一个写操作在另一个之前完成,并且依赖于不正确的数据。仍然会受到种族危险的影响。当然,但这不是问题所在。他这样做是有原因的。我怀疑:“这是我的第一个网络数据库”。工作得很好。测试它11次,尝试两位数的增长,并按预期工作。谢谢。@eggyal:向OP解释这一点会更有建设性。不管怎么说,我还在编辑。@eggyal:这是警告,不是解释。噢,我现在明白了。我应该在这里提交完整的代码。因此,此函数仅在用户完成表单并按下submit按钮时运行。因此,当表单加载时,它不会生成新的id。@user3324298:这不难猜测。竞争条件在这里是相当理论化的,因为人类与表单的交互非常缓慢,在计算机术语中很少发生,但如果两个用户“同时”提交表单,则可能发生这种情况。此外,该数据库是为本地intranet站点设计的。不到100个用户,我高度怀疑会出现两个用户同时按下提交按钮的情况。不过非常感谢。我会试试你的代码,如果行得通的话,请投票给我作为答案。请不要为标准语言函数创建你自己的函数。
function pad_number($number, $pad=10){
  $pad_zero = $pad - strlen($number.'');
  $nstr = '';
  for($i =0; $i< $pad_zero; $i++){
    $nstr .="0";
  }
  $nstr .= $number;
  return $nstr;
}
$newid = $idalpha . pad_number($newidnumeric);