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

时间:2016-02-22 14:25:07

标签: php postgresql 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约束的好处位)。

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

我认为一种hackish方式是检查异常详细信息并基于此生成友好的错误消息,但是我可以相信细节(如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语句的需要。仍然不完全满意这个解决方案,所以如果你知道更优雅的东西......

1 个答案:

答案 0 :(得分:2)

SQLSTATE代码在SQL标准中定义,不太可能发生变化。他们可能并不总是自己提供足够的信息(因此“细节”部分),但可以认为是可靠的。