How to insert a row and ignore only UNIQUE contraint errors, without using SELECT

感情迁移 提交于 2020-01-16 18:22:12

问题


I have a table with a column that must have UNIQUE values (but it could be also a multiple-column UNIQUE index, the problem is the same). In my PHP script I have to insert a row in that table.

I'm searching for a way, not MySQL-specific, to exit the PHP script if there's a problem, and the problem is not a violation of a UNIQUE constraint. To make things more easy I don't want to use a SELECT query before :D

Currently I'm doing something like this:

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();
    }
}

The problem is that this way I miss also errors related to foreign keys. I think it's okay if I can't have foreign keys problems inserting a new row, but what if I'll change the table in future? I could use

PDOStatement::errorInfo[1]

but it is a driver specific error code. The same with ON DUPLICATE KEY UPDATE.


回答1:


There isn't really a database-agnostic way to trap SQL errors.

The SQL standards define SQLSTATE as a two-character class followed by a three-character subclass. Some two-character classes are defined by the standards; others are defined by the implementation.

The standards define the two-character class '23' as "integrity constraint violation". They define only one subclass for '23'. It's '001', which means "restrict violation". But implementations vary. Although MySQL apparently defines only '23000', PostgreSQL defines at least six different subclasses for '23'. (PostgreSQL subclasses distinguish foreign key violations from unique violations.)

So it appears that the only way to know what MySQL means by SQLSTATE '23000' is to look at the MySQL error code. Error 1022 means "duplicate key"; 1216 and 1217 have to do with foreign key constraints.

It might be useful to look at the source code for various database "connectors" to see how they're implemented. The php source code is online. (I'd expect that to include PDO.) So is ruby's ActiveRecord.




回答2:


$someinsertquery = "INSERT IGNORE INTO table SET somecol=?";
$stmt = $dbh->prepare($someinsertquery);
$stmt->execute(array(($somecol)));
if ($stmt->rowCount()) {
    //everything is okay
}

Please note the all this try..catch..echo..exit stuff is omitted intentionally, as it is totally useless here.




回答3:


It's either that or do a select prior to insert to see if there will be a collision on any unique indexes.



来源:https://stackoverflow.com/questions/16696102/how-to-insert-a-row-and-ignore-only-unique-contraint-errors-without-using-selec

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!