我正在使用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语句的需要。仍然不完全满意这个解决方案,所以如果你知道更优雅的东西......