【问题标题】:Update/Delete violate foreign key on either side更新/删除在任一侧违反外键
【发布时间】:2021-08-03 13:28:03
【问题描述】:

我有两张桌子,下面是结构

CREATE TABLE IF NOT EXISTS nl_address (
  id int NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  address_text varchar(100),
  pincode varchar(6),
  city_id int NOT NULL,
  state_id int NOT NULL,
  country_id int NOT null,
  is_active boolean default true,
  PRIMARY KEY (id),
  CONSTRAINT fk_city_id FOREIGN KEY(city_id) REFERENCES nl_city(id),
  CONSTRAINT fk_state_id FOREIGN KEY(state_id) REFERENCES nl_state(id),
  CONSTRAINT fk_country_id FOREIGN KEY(country_id) REFERENCES nl_country(id)
);

CREATE TABLE IF NOT EXISTS nl_customer (
  cust_id int NOT NULL,
  prefix varchar(10) default 'CUST-',
  suffix varchar(2),
  org_name varchar(100) NOT NULL,
  domain_name varchar(100) NOT NULL,
  pan_number varchar(10) NOT null,
  pri_contact varchar(10) NOT NULL,
  pri_number varchar(10) NOT NULL,
  pri_email varchar(30) NOT NULL,
  sec_contact varchar(10),
  sec_number varchar(10),
  sec_email varchar(30),
  is_active boolean default true,
  addr_id int not null,
  created_date date,
  created_by varchar(10),
  updated_date date,
  updated_by varchar(10),
  PRIMARY KEY (cust_id),
  CONSTRAINT fk_address_id FOREIGN KEY(addr_id) REFERENCES nl_address(id)
);

问题是,我无法更新或删除 如果我尝试更新nl_address 中的记录,我会收到一个违规错误,即在`nl_customer 中使用了该字段。

如果我尝试从nl_customer 更新,则会收到一个违规错误,即该字段在nl_address 中使用

它起源于,当 JPA 试图持久化数据时,我插入了一个 id 为 1 的虚拟数据,当 JPA 试图插入另一条记录时它会抛出

.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "nl_address_pkey"
  Detail: Key (id)=(1) already exists.

表结构似乎有问题,感谢任何帮助

【问题讨论】:

  • 请添加您收到的删除/更新语句和错误文本。您所说的“如果我尝试从 nl_customer 更新,那么我收到违规错误”的意思不是很清楚。
  • 为避免主键违规,您可以在 Spring 实体中对主键使用自动增量或 @GeneratedValue(strategy = GenerationType.AUTO) 注释

标签: database postgresql spring-boot database-design


【解决方案1】:

实际上,如果您生成重复项,您无法更新或删除属于主键/外键的内容,这是很常见的,因为所有值都应该是唯一的(即,如果您已经 id=1 并将 id=2 更新为 id=1,你会得到你提到的错误)并且因为外键构造是一种特定的关系,所以应该澄清这种关系会发生什么。

  1. 在“nl_address”的情况下,您使用“GENERATED BY DEFAULT AS IDENTITY”,其目的与 SERIAL(即自动递增)相同,但它更符合 SQL 标准。 (我假设您也知道 GENERATED BY DEFAULT 和 GENERATED ALWAYS 之间的区别) 但是,您可以指定顺序以确保正确的自动增量功能。
ALTER TABLE nl_address 
ALTER COLUMN "id"
DROP IDENTITY IF EXISTS;

ALTER TABLE nl_address 
ALTER COLUMN "id"
ADD GENERATED BY DEFAULT AS IDENTITY (START WITH 1 INCREMENT 1);

如果您在 FOREIGN KEY 构造上使用 UPDATE 或 DELETE,请确保关系会发生什么:

[CONSTRAINT fk_name]
   FOREIGN KEY(fk_columns) 
   REFERENCES parent_table(parent_key_columns)
   [ON DELETE delete_action]
   [ON UPDATE update_action]

/* as delete_action or update_action you can use e.g. SET NULL, RESTRICT or CASCADE;
so ensure what happen with records in related table*/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 2019-03-05
    • 2021-05-09
    • 2019-11-05
    • 2017-11-18
    • 1970-01-01
    相关资源
    最近更新 更多