Do I really need to check that the the record in another table really exist, if PostgreSQL will check that foreign key constraint anyway?
Normaly you check if there is existing parent record, before creating child record. But it’s another query to execute. So I think if it would be better to just handle the PostgreSQL error and check if it was about that the parent record doesn’t exist (violates foreign key constraint).
Is it better to utilize database server capabilities, or it was not ment for this purpose?
Do you recommend to do all the integrity checking before creating new record?
CREATE TABLE "public"."categories" (
"id" serial,
"name" varchar(100),
CONSTRAINT "categories__id_pkey" PRIMARY KEY ("id")
);
CREATE TABLE "public"."products" (
"id" serial,
"category_id" integer NOT NULL,
"name" varchar(100),
CONSTRAINT "products__id_pkey" PRIMARY KEY ("id"),
CONSTRAINT "products__category_id_fkey" FOREIGN KEY ("category_id")
REFERENCES "categories" ("id") ON DELETE CASCADE
);
A pseudo-code:
if (query("SELECT * FROM categories WHERE id = 123"))
query("INSERT INTO products (category_id, name) VALUES (123, 'Something')")
else
throw Error("Parent record does not exist")
try
query("INSERT INTO products (category_id, name) VALUES (123, 'Something')")
catch (Exception e)
if (e.code == '23503')
throw Error("Parent record does not exist")
else
throw Error("Some other error occured")
Error code 23503 in PostgreSQL is:
ERROR: insert or update on table "products" violates foreign key constraint "products__category_id_fkey"
It was exactly meant for that purpose.
Just handle the error, otherwise you are doing too much work.
If you check for the existense of the related rows, you just duplicate the work as PostgreSQL will also do that.
If you don’t want to care in which order you insert the rows, you can declare the constraint as
deferrable initially deferred. In that case all related rows must exist when you commit your transaction, not when you run each statement. Here is a short example: http://sqlfiddle.com/#!12/33de1/1In that case you need handle errors when you commit, not when you run each statement.