3

为了防止将重复的用户名输入数据库并通知用户,在插入时使用异常捕获或在插入前选择查询是否更标准/更喜欢?

  1. 异常捕获:如果我尝试插入用户输入并且用户名已经存在,那么 SQL 数据库将抛出主键约束冲突异常。如果发生这种情况,我可以抓住它并做任何事情。

  2. 选择查询:如果它返回与用户名匹配的任何元组,那么我不会打扰插入。然后我可以显示错误消息。

我想在这里使用异常的主要优点是查询和行更少(速度更快?)。但是,我不认为这是一个例外情况,因为重复可能经常发生。

4

5 回答 5

4

至少,您应该尽可能使用选项 1 - 处理违反主键约束的情况,因为数据库是最后一个入口点。如果您检查代码中的重复项(尽管极不可能),仍然可能出现重复,因为在返回初始 SELECT 和返回 INSERT 语句之间存在延迟,并且另一个用户可能在该时间窗口中执行了相同的插入。

但是,首先运行选择以查看记录是否存在可能更有效,而不是每次都盲目地让插入运行。

所以我会推荐两者。

于 2013-07-01T20:03:15.250 回答
2

如果您使用Exception catching方法,即尝试插入,那么请记住一件事,当Exception您的counterfor发生时auto_increment column会增加让我们举个例子,您已成功插入一条记录,其id 为 1,然后您尝试插入相同的信息,然后得到异常您尝试插入另一个具有不同数据的数据 ,它将被插入但 id 没有。因为这次将是 3 而不是 2,因为发生异常时增加了 1,因此请记住,如果您使用 Exception 案例,当发生异常时,您将丢失这些 id 编号。如果您不关心 id 计数器,请继续执行此操作选项。

但我更喜欢先选择然后插入

希望有意义

于 2013-07-01T20:09:13.603 回答
0

除非,您的数据库查询层提供了多个异常类(对于每个 SQL 状态 - 在关系数据库的情况下),您不应该使用异常捕获;在这种情况下,您需要依赖异常的消息——它可能会随着时间而改变。

于 2013-07-01T20:04:12.500 回答
0

我认为实际上没有这样做的“标准”。要么你查询,然后插入,要么你去 INSERT / 异常。

如果应用正确,两者都可以正常工作。

我通常更喜欢让数据库来完成这项任务。更改您的表,以便您希望唯一的字段实际上是唯一索引。当您要插入数据并且它是重复的时,您将收到一个错误,可用于决定下一步做什么。ON DUPLICATE KEY或者,如果您想执行另一个表操作,则可以使用(如果在您选择的 RDBMS 上可用)(如果需要)。

这避免了在数据库方面出现问题,如果不仅仅是您的应用程序写入这些表。即使您首先查询,您也应该这样做以得到一个可靠的表。

于 2013-07-01T20:04:53.097 回答
0

IGNORE 子句怎么样:

CREATE TABLE `users` (
`username` VARCHAR(16),
PRIMARY_KEY (`username`)
);

INSERT IGNORE INTO `users`
(`username`)
VALUES ('Foo Dude');

这将产生一个警告,但不会终止。

显然,您可以使用以下内容在 PHP 5.1.0 及更高版本中捕获该警告:

function exception_error_handler($severity, $message, $errfile, $errline)
{
    if (error_reporting()) { // skip errors that were muffled
        throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
    }

    // Or handle in some other way, like filtering for the WARNING
    // that is generated by the INSERT IGNORE.
}

set_error_handler("exception_error_handler");

但是,我没有尝试过这个。查看“ErrorException”[ http://php.net/errorexception]的 PHP 手册,尤其是注释——考虑实现自己的“ErrorException”类,在其中过滤使用 INSERT IGNORE 时重复键插入生成的 WARNING。

或者

显然 error_get_last() 也会收到警告。

如果您不希望这些警告出现在日志中,那么要么使用 error_reporting() 来抑制它们,或者尝试在查询函数前面放置一个 '@' [谨慎使用'因为这将抑制所有错误/警告!]:

@mysqli_query($query);
于 2015-05-02T20:35:36.403 回答