如何根据MySQL的现有值获取下一个字母数字ID

Dav*_*dom 7 php mysql

首先,我很抱歉,如果以前曾经问过这个问题 - 事实上我确定它有,但我找不到它/找不到要搜索的东西.

我需要根据公司名称生成唯一的快速参考ID.例如:

Company Name                Reference
Smiths Joinery              smit0001
Smith and Jones Consulting  smit0002
Smithsons Carpets           smit0003

这些都将存储在MySQL表的varchar列中.数据将被收集,转义和插入,如'HTML - > PHP - > MySQL'.ID应该是上面描述的格式,四个字母,然后是四个数字(最初至少 - 当我到达smit9999它时只会溢出到5个数字).

我可以处理从公司名称生成4个字母,我将直接通过名称,直到我收集了4个字母字符,strtolower()然后我 - 然后我需要获得下一个可用的数字.

最好/最简单的方法是什么,以便消除重复的可能性?

目前我在想:

$fourLetters = 'smit';
$query = "SELECT `company_ref`
            FROM `companies`
          WHERE
            `company_ref` LIKE '$fourLetters%'
          ORDER BY `company_ref` DESC
          LIMIT 1";
$last = mysqli_fetch_assoc(mysqli_query($link, $query));
$newNum = ((int) ltrim(substr($last['company_ref'],4),'0')) + 1;
$newRef = $fourLetters.str_pad($newNum, 4, '0', STR_PAD_LEFT);
Run Code Online (Sandbox Code Playgroud)

但是,如果两个用户尝试输入同时导致相同ID的公司名称,我可以看到这会导致问题.我将在列上使用唯一索引,因此它不会导致数据库中出现重复,但仍会导致问题.

当我进行插入时,有没有人能想到让MySQL为我工作的方法,而不是事先在PHP中计算它?

请注意,实际代码将是OO并将处理错误等 - 我只是想知道是否有更好的方法来执行此特定任务,它更多的是关于SQL而不是其他任何东西.

编辑

我认为@ EmmanuelN建议使用MySQL触发器可能是解决这个问题的方法,但是:

  • 我不熟悉MySQL,特别是触发器,以实现这一点,并且想要一个创建,添加和使用触发器的分步示例.
  • 我仍然不确定这是否会消除生成两个相同ID的可能性.见what happens if two rows are inserted at the same time that result in the trigger running simultaneously, and produce the same reference? Is there any way to lock the trigger (or a UDF) in such a way that it can only have one concurrent instance?.

或者我会接受任何其他建议的解决此问题的方法.

Bre*_*ley 7

如果您使用的是MyISAM,则可以在文本字段+自动增量字段上创建复合主键.MySQL将自动处理递增数字.它们是单独的字段,但您可以获得相同的效果.

CREATE TABLE example (
company_name varchar(100),
key_prefix char(4) not null,
key_increment int unsigned auto_increment,
primary key co_key (key_prefix,key_increment)
) ENGINE=MYISAM;
Run Code Online (Sandbox Code Playgroud)

当您在表格中插入时,该key_increment字段将根据基于的最高值递增key_prefix.所以插入key_prefix"smit"将从1开始key_inrement,key_prefix"jone"将从1开始key_inrement,等等.

优点:

  • 您无需为计算数字做任何事情.

缺点:

  • 您的密钥分为2列.
  • 它不适用于InnoDB.