【问题标题】:POSTGRESQL. Insert or update on table violates foreign key constraint后GRESQL。在表上插入或更新违反外键约束
【发布时间】:2020-09-07 20:53:48
【问题描述】:

我是 Posgresql 的新手。我有 5 个表,我正在尝试向表中插入属性。当我第二次尝试插入时,“pgadmin”中出现此错误。

ERROR: insert or update on table "question" violates foreign key constraint "question_id_difficulty_fkey" DETAIL: Key (id_difficulty)=(9) is not present in table "difficulty". SQL state: 23503.

我的架构在这里

  id SERIAL PRIMARY KEY,
  name varchar
);

CREATE TABLE question (
  id SERIAL PRIMARY KEY,
  text varchar,
  correct_answer varchar,
  incorrect_answer1 varchar,
  incorrect_answer2 varchar,
  incorrect_answer3 varchar,
  id_difficulty SERIAL REFERENCES difficulty(id),
  id_category SERIAL REFERENCES category (id),
  id_creator SERIAL REFERENCES game (id)
);

CREATE TABLE difficulty (
  id SERIAL PRIMARY KEY,
  name varchar
);

CREATE TABLE category (
  id SERIAL PRIAMRY KEY,
  name varchar
);

CREATE TABLE user (
  id SERIAL PRIMARY KEY,
  name varchar
)


【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    您需要在难度表中对应一个 id 为 9 的条目,以便在问题表中引用 id_difficulty 列。

    例如,如果您的难度表包含:

     id |      name      
    ----+----------------
      1 | easy
      2 | reasonable
      3 | difficult
      4 | very difficult
      5 | impossible
    

    您只能将问题表中行的 id_difficulty 设置为这些 id 值之一。如果您设置 6、12 或 1 到 5 以外的任何值,则会失败,因为这些值受外键值的约束。

    id_difficulty、id_category 和 id_creator 列不应使用 serial,因此应删除它们的默认值:

    ALTER TABLE question ALTER COLUMN id_difficulty DROP DEFAULT;
    ALTER TABLE question ALTER COLUMN id_category DROP DEFAULT;
    ALTER TABLE question ALTER COLUMN id_creator DROP DEFAULT;
    

    【讨论】:

    • 感谢您的帮助。每次尝试插入后,此数字都会增加
    • 我认为这些列被错误地设置为serial。这意味着如果在插入行时没有明确指定该值,它将从其序列中选择下一个值。对于引用另一个表上的列的列,情况不应如此。这些应该只是没有序列的 int 列。你可以禁用序列,我会用 DDL 更新我的答案。
    • 我用另一种方式解决了它,它设置了 INSERT 定义中所有表的所有外键。但我确实认为这不是一个很好的解决方案
    • 我仍然建议您删除这些列上的默认值,因为序列没有用处。
    • 是的,但是每次我猜都​​必须通过难度级别。
    【解决方案2】:

    Postgres now recommends using generated always as instead of serial. 如果你这样做,那么类型将更简单地对齐:

    CREATE TABLE question (
      id int generated always as identity PRIMARY KEY,
      text varchar,
      correct_answer varchar,
      incorrect_answer1 varchar,
      incorrect_answer2 varchar,
      incorrect_answer3 varchar,
      id_difficulty int REFERENCES difficulty(id),
      id_category int REFERENCES category (id),
      id_creator int REFERENCES game (id)
    );
    
    CREATE TABLE difficulty (
      id int generated always as identity PRIMARY KEY,
      name varchar
    );
    

    这使得正在发生的事情更加清晰。外键引用的数据类型需要与主键的数据类型相匹配。 Postgres 知道serial 真的是int。但是使用generated always,很明显它们是一样的。

    另外,generated always as 更符合标准 SQL。

    【讨论】:

      猜你喜欢
      • 2011-01-27
      • 2020-12-02
      • 2015-08-19
      • 2020-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-06
      • 2019-06-16
      相关资源
      最近更新 更多