处理PostgreSQL外键错误与防止它们发生

Taa*_*aai 2 sql postgresql

我是否真的需要检查另一个表中的记录是否真的存在,如果PostgreSQL还是会检查外键约束?

Normaly parent在创建child记录之前检查是否存在记录.但这是另一个执行查询.所以我认为如果只处理PostgreSQL错误并检查是否parent存在记录不存在(违反外键约束)会更好.

是否更好地利用数据库服务器功能,或者它没有用于此目的?您是否建议在创建新记录之前进行所有完整性检查?

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
);
Run Code Online (Sandbox Code Playgroud)

伪代码:

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")
Run Code Online (Sandbox Code Playgroud)

23503PostgreSQL中的错误代码是:

ERROR: insert or update on table "products" violates foreign key constraint "products__category_id_fkey"

a_h*_*ame 5

是否更好地利用数据库服务器功能,或者它没有用于此目的

完全是为了这个目的.

只是处理错误,否则你做了太多的工作.

如果检查相关行的存在,则只需复制工作,因为PostgreSQL也会这样做.

如果您不想关心插入行的顺序,可以将约束声明为deferrable initially deferred.在这种情况下,所有相关的行必须在提交事务时存在,而不是在运行每个语句时.这是一个简短的例子:http://sqlfiddle.com/#!12/33de1/1

在这种情况下,您在提交时需要处理错误,而不是在运行每个语句时.