【问题标题】:How to insert a row and ignore only UNIQUE contraint errors, without using SELECT如何在不使用 SELECT 的情况下插入一行并仅忽略 UNIQUE 约束错误
【发布时间】:2013-05-17 18:15:28
【问题描述】:

我有一个表,其中的列必须具有 UNIQUE 值(但它也可能是多列 UNIQUE 索引,问题是一样的)。在我的 PHP 脚本中,我必须在该表中插入一行。

我正在寻找一种方法,而不是特定于 MySQL,如果出现问题,则退出 PHP 脚本,而问题是不是违反 UNIQUE 约束。为了让事情变得更简单,我不想在之前使用 SELECT 查询:D

目前我正在做这样的事情:

try
{
    $stmt = $dbh->prepare($someinsertquery);
    $stmt->bindParam(':somecol', $somecol);

    $stmt->execute();
}
catch (PDOException $e)
{
    $errcode = $e->getCode();

    if (! ($e->getCode() === '23000'))
    {
        echo 'Error inserting into db: ' . $e->getMessage();
        var_dump($e->getTrace());

        exit();
    }
}

问题是这样我也错过了与外键相关的错误。我认为如果我在插入新行时不会出现外键问题,那没关系,但如果我将来更改表怎么办?我可以使用

PDOStatement::errorInfo[1]

但它是driver specific error code。与 ON DUPLICATE KEY UPDATE 相同。

【问题讨论】:

    标签: php database exception pdo unique-constraint


    【解决方案1】:

    要么就是这样,要么在插入之前进行选择以查看是否会在任何唯一索引上发生冲突。

    【讨论】:

    • 是的,但我想知道该错误代码是否意味着我违反了一些 UNIQUE 约束。如果我执行 SELECT 我会确定,但我更愿意捕获异常。
    • 您可以保证至少是问题所在。它只响应一个错误,所以如果请求有其他问题,你不会知道
    【解决方案2】:
    $someinsertquery = "INSERT IGNORE INTO table SET somecol=?";
    $stmt = $dbh->prepare($someinsertquery);
    $stmt->execute(array(($somecol)));
    if ($stmt->rowCount()) {
        //everything is okay
    }
    

    请注意,所有这些 try..catch..echo..exit 的东西都被故意省略了,因为它在这里完全没用。

    【讨论】:

    • 问题是我想确定错误是由违反 UNIQUE 约束引起的。使用我的代码,我可能会错过其他一些违反约束的情况。使用您的代码 all 会忽略错误。
    • 怎么样?定义“忽略”?例如哪一个?
    • 好吧,例如看这篇文章:stackoverflow.com/questions/548541/…。我可以使用“ON DUPLICATE KEY UPDATE”,但至于 errorInfo,这是 MySQL 特有的。
    • 我不明白这里重复做什么。您是否发现此代码有任何某些问题?
    • 我必须承认我误解了 INSERT IGNORE 究竟做了什么......我认为它也忽略了外键约束。它有效,并且是一个很好的解决方案。不幸的是,它只适用于 MySQL……我正在寻找一个通用的解决方案,但我开始认为没有这样的解决方案。也许最好的解决方案是做一个函数,给定数据库,为您提供数据库用来识别唯一约束违规的错误代码。
    【解决方案3】:

    实际上并没有一种与数据库无关的方法来捕获 SQL 错误。

    SQL 标准将 SQLSTATE 定义为两个字符的类,后跟一个三字符的子类。标准定义了一些两字符类;其他由实现定义。

    标准将两字符类“23”定义为“违反完整性约束”。他们只为“23”定义了一个子类。它是'001',意思是“限制违规”。但实现方式各不相同。虽然 MySQL 显然只定义了 '23000',但 PostgreSQL defines at least six different subclasses 定义为 '23'。 (PostgreSQL 子类将外键违规与唯一违规区分开来。)

    所以看来,了解 MySQL 的 SQLSTATE '23000' 意味着什么的唯一方法是查看MySQL error code。错误 1022 表示“重复密钥”; 1216 和 1217 与外键约束有关。

    查看各种数据库“连接器”的源代码以了解它们是如何实现的 可能很有用。 php source code 在线。 (我希望这包括 PDO。)ruby's ActiveRecord 也是如此。

    【讨论】:

    • 是的,但如果错误代码不等于“23000”,我会退出脚本。我正在寻找一种方法,而不是特定于 MySQL,仅在出现问题并且问题不是违反 UNIQUE 约束时才退出脚本。
    • 除了磁盘已满,我真的不知道在这种情况下我的脚本应该做什么......无论如何这并不能回答我的问题。
    • 我已经重写了我的答案。我今天似乎过着无脑的一天。我现在就闭嘴。
    • 谢谢,这对了解很有用(网上关于 SQLSTATE 的内容很少)。我想我会放弃异常捕获并采用@YourCommonSense 解决方案,因为再三考虑它允许我不立即提交查询。可惜数据库好像没有详细的通用错误处理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-23
    • 2010-10-28
    • 2021-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多