PHP / MySQLi - 捕获唯一ID冲突

3
我想知道是否有一种简单的方法来检查INSERT语句在执行INSERT时是否因MySQL字段上的唯一索引而触发冲突。
例如,假设我正在向数据库添加一个用户,而username是唯一索引:
$sql = new MySQLi(...);
$res = $sql->query('INSERT INTO `users` (`username`) VALUES ("john_galt");');

一个名为john_galt的用户已经存在,因此不会执行INSERT操作。但是我该如何最好地向用户响应有意义的错误(即用户名已存在,请选择一个唯一的名称)?
我想到了几个方法,比如检查insert_id是否设置--如果查询生成错误,则不应设置。但是那个错误可能是任何东西。
同样,我可以检查$sql->error是否为空,但是,同样,它也可能是任何东西--语法错误、格式不正确的值或其他任何东西。显然,我不会向最终用户输出实际的MySQL错误。
我能想到的两个解决方案是:
在运行INSERT之前,运行SELECT TRUE FROM ``users`` WHERE ``username`` = "john_galt";以查看数据库中是否已经存在该用户名,但是我觉得我已经向该字段添加了唯一约束,所以不必这样做--否则就失去了目的。 strpos($sql->error, 'Duplicate entry') === 0--似乎非常hackish。
是否有更好的方法来使用PHP的MySQLi类确定这一点?

1
我建议在尝试 INSERT 之前先进行验证。这比预期的失败更节省时间。 :) - jhnferraris
1
嗯,这不会是一个意外的失败……如果我必须在插入另一行之前手动检查其存在,那么拥有一个唯一字段(即除了主索引之外)的意义是什么? - M Miller
我同意这是拥有唯一字段的关键所在,提前检查没有内在价值。在大多数情况下,有效的插入操作比冲突要常见得多,因此更有效的方法是直接进行插入并响应错误条件。 - xtempore
1个回答

8

谢谢!我从未想过这个!如果 PHP 的 MySQLi 类在某个地方包含了这些常量,那将是很酷的事情,这样我就不用使用文字错误代码了。 - M Miller
我可能不太需要那么具体,但是如果有多个字段具有唯一约束条件并且错误消息应更具体,是否也可以提取字段的名称? - M Miller
1
@MMiller 除了使用某种正则表达式从返回的错误字符串中提取字段名之外,我不知道还有什么其他方法可以做到这一点。使用这种方法的问题是,即使有多个重复的唯一字段,MySQL也只会在遇到第一个时返回错误。顺便说一句,如果您需要同时使用错误字符串和错误代码,请查看 error_list,它将所有这些信息都封装在一个数组中返回。 - StathisG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接