programing

Postgre에서 외부 키가 있는 행 삭제SQL

bestprogram 2023. 5. 7. 12:04

Postgre에서 외부 키가 있는 행 삭제SQL

외부 키가 포함된 행을 삭제하고 싶지만 다음과 같은 작업을 시도할 때:

DELETE FROM osoby WHERE id_osoby='1'

나는 다음과 같은 진술을 받습니다.

오류: "osoby" 테이블의 업데이트 또는 삭제가 "kontakty" 테이블의 외부 키 제약 조건 "kontakty_ibfk_1"을(를) 위반합니다. detail: 키(id_osoby)=(1)는 여전히 "kontakty" 테이블에서 참조됩니다.

이 행을 삭제하려면 어떻게 해야 합니까?

이를 자동화하기 위해 외부 키 제약 조건을 다음과 같이 정의할 수 있습니다.ON DELETE CASCADE.
외부제약 조건에 대한 설명서를 인용합니다.

CASCADE참조된 행을 삭제할 때 해당 행을 참조하는 행도 자동으로 삭제되도록 지정합니다.

다음과 같이 현재 FK 정의를 검색합니다.

SELECT pg_get_constraintdef(oid) AS constraint_def
FROM   pg_constraint
WHERE  conrelid = 'public.kontakty'::regclass  -- assuming public schema
AND    conname = 'kontakty_ibfk_1';

그런 다음 추가 또는 수정ON DELETE ...의 일부.ON DELETE CASCADE(다른 모든 것을 그대로 보존) 다음과 같은 성명서에서:

ALTER TABLE kontakty
   DROP CONSTRAINT kontakty_ibfk_1
 , ADD  CONSTRAINT kontakty_ibfk_1
   FOREIGN KEY (id_osoby) REFERENCES osoby (id_osoby) ON DELETE CASCADE;

거기에는 없다ALTER CONSTRAINT지휘권제약 조건을 하나로 삭제하고 다시 만들기ALTER TABLE동시 쓰기 액세스로 발생할 수 있는 레이스 조건을 방지하기 위한 명령문입니다.

분명히 그렇게 하기 위해서는 특권이 필요합니다.작업에 필요한 시간:ACCESS EXCLUSIVE테이블에 고정된kontakty그리고 aSHARE ROW EXCLUSIVE테이블에 고정된osoby.

할 수 없다면,ALTER테이블, 수동(한 번) 또는 트리거에 의해 삭제BEFORE DELETE(매번)이 나머지 옵션입니다.

일반적인 솔루션으로 권장해서는 안 되지만, 운영되지 않거나 현재 사용 중인 데이터베이스의 행을 일회성으로 삭제하는 경우 해당 테이블에서 트리거를 일시적으로 비활성화할 수 있습니다.

저의 경우 개발 모드에 있으며 외부 키를 통해 서로를 참조하는 테이블이 몇 개 있습니다.따라서 내용을 삭제하는 것은 한 테이블에서 다른 테이블 앞에 있는 모든 행을 삭제하는 것만큼 간단하지 않습니다.그래서, 저는 다음과 같이 그들의 내용을 삭제하는 것이 잘 작동했습니다.

ALTER TABLE table1 DISABLE TRIGGER ALL;
ALTER TABLE table2 DISABLE TRIGGER ALL;
DELETE FROM table1;
DELETE FROM table2;
ALTER TABLE table1 ENABLE TRIGGER ALL;
ALTER TABLE table2 ENABLE TRIGGER ALL;

물론 데이터베이스의 무결성을 손상시키지 않도록 주의하면서 원하는 대로 WHERE 절을 추가할 수 있어야 합니다.

http://www.openscope.net/2012/08/23/subverting-foreign-key-constraints-in-postgres-or-mysql/ 에서 관련된 좋은 토론이 있습니다.

외부 키가 여전히 다른 테이블을 참조하는 경우 삭제할 수 없습니다.먼저 참조를 삭제합니다.

delete from kontakty
where id_osoby = 1;

DELETE FROM osoby 
WHERE id_osoby = 1;

이 질문을 받은 지 오래되었는데, 희망이 도움이 될 수 있습니다.DB 구조를 변경하거나 변경할 수 없으므로 이 작업을 수행할 수 있습니다.postgresql 문서에 따르면.

잘라내기 - 표 또는 표 집합을 비웁니다.

TRUNCATE [ TABLE ] [ ONLY ] name [ * ] [, ... ]
    [ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]

묘사

잘라내기는 테이블 집합에서 모든 행을 빠르게 제거합니다.각 테이블에서 정규화되지 않은 DELETE와 동일한 효과를 가지지만 실제로 테이블을 스캔하지 않기 때문에 더 빠릅니다.또한 이후 진공 작업을 수행할 필요 없이 디스크 공간을 즉시 회수합니다.이것은 큰 테이블에서 가장 유용합니다.


테이블 다른 테이블을 잘라내고 외부 키 제약 조건을 통해 다른 테이블을 참조하는 테이블로 캐스케이드합니다.

TRUNCATE othertable CASCADE;

마찬가지로 연결된 시퀀스 생성기도 재설정합니다.

TRUNCATE bigtable, fattable RESTART IDENTITY;

연결된 시퀀스 생성기를 잘라내고 재설정합니다.

TRUNCATE revinfo RESTART IDENTITY CASCADE ;

그것은 표에 있는 것을 의미합니다.kontakty 는하행있다습니이조행에 행을 .osoby삭제할 항목입니다.먼저 해당 행을 삭제하거나 테이블 간의 관계에 대해 계단식 삭제를 설정해야 합니다.

파우드제니아!

를 통해 관련 레코드를 삭제하는 추가 SQL 스크립트를 실행하면 이를 달성할 수 있습니다.FK.

위해 를이 위다음사선용의 합니다.WHERE의 절DELETE명령은 필요한 것을 간단히 수행할 수 있습니다.

다음과 유사한 것:

DELETE FROM kontakty 
    WHERE fk_column_from_kontakty_matching_id_osoby IN (
        SELECT id_osoby FROM osoby WHERE id_osoby = '1'
    );


DELETE FROM osoby WHERE id_osoby = '1';
  • 이 예는 다음을 가정합니다.FK의 열kontaktyosoby.id_osoby를 합다니고라고 합니다.fk_column_from_kontakty_matching_id_osoby 수 입니다.
  • OP의 경우 쿼리가 많이 단순화될 수 있지만, 더 복잡한 시나리오를 달성하는 것을 보여주기 때문에 이렇게 남겨두기로 결정했습니다.
  • 방식은 된 SQL 할 수 유용합니다.id그리고 어디서ids는 먼저 쉽게 가져올 수 없고 나중에 실행될 수 없습니다.

언급URL : https://stackoverflow.com/questions/14182079/delete-rows-with-foreign-key-in-postgresql