How to return original row in Postgres upon violating a unique constraint

☆樱花仙子☆ 提交于 2020-12-12 11:08:05

问题


In Postgres, if you try to insert a value that has a Unique Index on it, you'll see the following:

duplicate key value violates unique constraint "testing_email_key"
 DETAIL: Key (email)=(email@domain.com) already exists.

In my case, I actually (upon failing this way) want the original row with email = email@domain.com. Sort of like a RETURNING statement, but for a failed insert.

Is there a way to do this in Postgres?

Right now I actually just parse the error message in Python above, then re-issue a SELECT to get the original row, but seems like this is something that should be able to be done in a single query.


回答1:


This actually is not possible to do in a single query, you'll need to use a function to check the original row, that it's exactly what you're doing then in Python. You can see more information in the postgresql documentation

If you want to perform the wish behaviour in postgresql instead of Python, you can do a pgplsql function, catch the exception and do the SELECT statement (some questions related with this solution: this and this)

Edit This could be the alternative pgplsql solution:

CREATE OR REPLACE FUNCTION udf_insert_row(
    param_email varchar)
  RETURNS integer AS
$BODY$

DECLARE
    result integer;

BEGIN
  /*
  -- To Test:
    SELECT udf_insert_row('admin@admin.com'); will return 1
    SELECT udf_insert_row('admin2@admin.com'); will return 2
    SELECT udf_insert_row('admin@admin.com'); will return 1
  */

  BEGIN
      INSERT INTO your_table(
        email
        ) 
      VALUES (
        param_email
      ) RETURNING id INTO result;
  EXCEPTION WHEN unique_violation THEN
      SELECT 
        id INTO STRICT result
      FROM 
        your_table 
      WHERE 
        email = param_email;
  END;  

    RETURN result;

END;

$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION udf_insert_row(varchar)
  OWNER TO postgres;

Then in python, you can call the function like this:

pgcur.execute("BEGIN")
args = ["admin@admin.com"]
pgcur.callproc("udf_insert_row",args)
result = pgcur.fetchone()
pgcur.execute("COMMIT")

You can accept this as a valid answer if it's useful



来源:https://stackoverflow.com/questions/58897282/how-to-return-original-row-in-postgres-upon-violating-a-unique-constraint

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