使用 PHP PDO 处理失败的 UNIQUE 约束


Handle failed UNIQUE constraint using PHP PDO?

我正在使用PostgreSQL和PHP(使用PDO)构建一个简单的Web应用程序。我在一列上有一个 UNIQUE 约束,现在我正在尝试如何最好地处理将重复项插入该数据库表的尝试。

我是否必须首先显式运行 SELECT 语句并检查我要插入的值是否已存在,或者我可以使用 PDO 异常来处理它?

现在我正在做

    try{
        $stmt = $pdo->prepare("INSERT INTO table (column) VALUES (?) RETURNING id;");
        $stmt->execute( array('duplicate') );
    }
    catch( PDOException $e ){
        print $e;
    } 

这给了我

exception 'PDOException' with message 'SQLSTATE[23505]: Unique violation: 7 ERROR:  duplicate key value violates unique constraint "column"
DETAIL:  Key (column)=(duplicate) already exists.'

我认为在错误发生时能够拾取错误会更干净,而不是首先检查该值是否已存在(这首先破坏了拥有 UNIQUE 约束的好处)。

最后,我想向用户显示一条用户友好的错误消息,例如"用户名已存在"。

我想一种黑客方法是检查异常详细信息并基于此生成我友好的错误消息,但是我可以相信详细信息(如 SQLSTATE[23505] 或 code=7)将来不会改变吗?

我是否可以构建一个更好的 SQL 语句,在重复约束失败时返回有用的内容(以及成功的 id,就像现在一样)?

编辑

创建存储过程可能是一种解决方案:

CREATE OR REPLACE FUNCTION my_insert(a_value text)
RETURNS text AS $$
DECLARE
 retval text;
BEGIN
    INSERT INTO table (column) VALUES (a_value) RETURNING id INTO retval;
    RETURN retval;
    EXCEPTION
        WHEN unique_violation THEN
            retval = 'duplicate';
            RETURN retval;
END;
$$ LANGUAGE plpgsql;

,然后检查返回值是 'duplicate' 还是 id。

虽然它不允许我利用 PHP 异常来确定出了什么问题并生成友好的错误消息,但它确实消除了对单独的 SELECT 语句的需求。仍然不完全满意这个解决方案,所以如果你知道更优雅的东西......

SQLSTATE 代码在 SQL 标准中定义,不太可能更改。它们本身可能并不总是提供足够的信息(因此是"详细信息"部分),但可以被认为是可靠的。