问题
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