2

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

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
);

一个伪代码:

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")

PostgreSQL 中的错误代码23503是:

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

4

1 回答 1

5

是更好地利用数据库服务器功能,还是没有为此目的

正是为此目的。

只需处理错误,否则您做的工作太多。

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

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

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

于 2012-10-23T16:30:50.413 回答