5

要创建表,我使用:

CREATE TABLE category
(
  cat_id serial NOT NULL,
  cat_name character varying NOT NULL,
  parent_id integer NOT NULL,
  CONSTRAINT cat_id PRIMARY KEY (cat_id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE category
  OWNER TO pgsql;

parent_id 是另一个类别的 id。现在我有一个问题:如何级联删除记录及其子项?我需要将 parent_id 设置为 cat_id 的外键。我试试这个:

  ALTER TABLE category 
ADD CONSTRAINT cat_cat_id_fkey FOREIGN KEY (parent_id)
      REFERENCES category (cat_id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE

但它属于:

ERROR:  insert or update on table "category" violates foreign key constraint "cat_cat_id_fkey"
DETAIL:  Key (parent_id)=(0) is not present in table "category".
4

3 回答 3

6

您遇到的问题 -parent_id层次结构顶部的类别是什么?

如果会null- 它会打破NOT NULL约束。

如果它将是一些任意数字,例如0- 它会破坏外键(如您的示例中)。

常见的解决方案 - 将NOT NULLconstratint 放在顶部类别中parent_id并设置parent_id为。null

于 2013-06-29T10:45:24.210 回答
3
-- create some fake data for testing
--
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;
CREATE TABLE category

(
  cat_id serial NOT NULL,
  cat_name character varying NOT NULL,
  parent_id integer NOT NULL,
  CONSTRAINT cat_id PRIMARY KEY (cat_id)
);

INSERT INTO category(cat_name,parent_id)
SELECT 'Name_' || gs::text
        , gs % 3
FROM generate_series(0,9) gs
        ;

        -- find the records with the non-existing parents
SELECT ca.parent_id , COUNT(*)
FROM category ca
WHERE NOT EXISTS (
        SELECT *
        FROM category nx
        WHERE nx.cat_id = ca.parent_id
        )
GROUP BY ca.parent_id
        ;

        -- if all is well: proceed
        -- make parent pointer nullable
ALTER TABLE category
        ALTER COLUMN parent_id DROP NOT NULL
        ;

        -- set non-existing parent pointers to NULL
UPDATE category ca
SET parent_id = NULL
WHERE NOT EXISTS (
        SELECT *
        FROM category nx
        WHERE nx.cat_id = ca.parent_id
        )
        ;

        -- Finally, add the FK constraint
ALTER TABLE category
        ADD CONSTRAINT cat_cat_id_fkey FOREIGN KEY (parent_id)
              REFERENCES category (cat_id) MATCH SIMPLE
              ON UPDATE CASCADE ON DELETE CASCADE
        ;
于 2013-06-29T12:21:56.510 回答
1

这很简单。
这里的外键parent_id是指cat_id.
这里有一条记录parent_id=0存在,但没有一条记录cat_id=0

于 2013-09-16T06:21:52.293 回答