PostgreSQL 에서 enable,disable,vaidate 외 키 로 구 속 된 인 스 턴 스
11536 단어 PostgreSQLenabledisablevalidate
postgres=# create table t1(a int primary key,b text,c date);
CREATE TABLE
postgres=# create table t2(a int primary key,b int references t1(a),c text);
CREATE TABLE
postgres=# insert into t1 (a,b,c) values(1,'aa',now());
INSERT 0 1
postgres=# insert into t1 (a,b,c) values(2,'bb',now());
INSERT 0 1
postgres=# insert into t2 (a,b,c) values (1,1,'aa');
INSERT 0 1
postgres=# insert into t2 (a,b,c) values (2,2,'aa');
INSERT 0 1
postgres=# \d t1
Table "public.t1"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
a | integer | | not null |
b | text | | |
c | date | | |
Indexes:
"t1_pkey" PRIMARY KEY, btree (a)
Referenced by:
TABLE "t2" CONSTRAINT "t2_b_fkey" FOREIGN KEY (b) REFERENCES t1(a)
postgres=# \d t2
Table "public.t2"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
a | integer | | not null |
b | integer | | |
c | text | | |
Indexes:
"t2_pkey" PRIMARY KEY, btree (a)
Foreign-key constraints:
"t2_b_fkey" FOREIGN KEY (b) REFERENCES t1(a)
postgres=#
만약 우리 가 스 크 립 트 를 통 해 표 에 데 이 터 를 불 러 오고 싶다 고 가정 합 니 다.스 크 립 트 에 불 러 오 는 순 서 를 모 르 기 때문에 표 t2 의 외 키 제약 을 사용 하지 않 기로 결 정 했 습 니 다.데이터 불 러 온 후에 외 키 제약 을 불 러 오기 로 결 정 했 습 니 다.
postgres=# alter table t2 disable trigger all;
ALTER TABLE
postgres=#
여기 가 좀 이상해 보일 수도 있 지만,외부 키 의 제약 을 사용 하지 않 는 것 은 사실이다.다른 외 키 제약 이 있다 면 당연히 사용 하지 않 습 니 다.시계 t2 를 다시 봅 시다.
postgres=# \d t2
Table "public.t2"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
a | integer | | not null |
b | integer | | |
c | text | | |
Indexes:
"t2_pkey" PRIMARY KEY, btree (a)
Foreign-key constraints:
"t2_b_fkey" FOREIGN KEY (b) REFERENCES t1(a)
Disabled internal triggers:
"RI_ConstraintTrigger_c_75213" AFTER INSERT ON t2 FROM t1 NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE PROCEDURE "RI_FKey_check_ins"()
"RI_ConstraintTrigger_c_75214" AFTER UPDATE ON t2 FROM t1 NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE PROCEDURE "RI_FKey_check_upd"()
postgres=#
키워드 all 은 표 의 다른 내부 트리거 도 사용 하지 않 습 니 다.슈퍼 서가 있어 야 실행 할 수 있 습 니 다.
postgres=# create user abce with login password 'abce';
CREATE ROLE
postgres=# \c postgres abce
You are now connected to database "postgres" as user "abce".
postgres=> create table t3 ( a int primary key, b text, c date);
CREATE TABLE
postgres=> create table t4 ( a int primary key, b int references t3(a), c text);
CREATE TABLE
postgres=> alter table t4 disable trigger all;
ERROR: permission denied: "RI_ConstraintTrigger_c_75235" is a system trigger
postgres=>
그럼 일반 사용자 로 서 트리거 를 어떻게 사용 하지 않 습 니까?
postgres=> alter table t4 disable trigger user;
구체 적 인 문법 은:
DISABLE TRIGGER [ trigger_name | ALL | USER ]
t1,t2 표 로 돌아 갑 니 다.
postgres=# select * from t1;
a | b | c
---+----+------------
1 | aa | 2020-11-04
2 | bb | 2020-11-04
(2 rows)
postgres=# select * from t2;
a | b | c
---+---+----
1 | 1 | aa
2 | 2 | aa
(2 rows)
postgres=# insert into t2 (a,b,c) values (3,3,'cc');
INSERT 0 1
postgres=#
t1 에 일치 하지 않 는 기록 을 삽입 하 였 으 나 삽입 에 성공 하 였 습 니 다.
postgres=# alter table t2 enable trigger all;
ALTER TABLE
postgres=# \d t2
Table "public.t2"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
a | integer | | not null |
b | integer | | |
c | text | | |
Indexes:
"t2_pkey" PRIMARY KEY, btree (a)
Foreign-key constraints:
"t2_b_fkey" FOREIGN KEY (b) REFERENCES t1(a)
postgres=# alter table t2 validate constraint t2_b_fkey;
ALTER TABLE
postgres=#
PostgreSQL 에 일치 하지 않 는 기록 이 보고 되 지 않 았 다 는 것 이 놀 랍 지 않 습 니까?왜 일 까요?pg 보기constraint:
postgres=# select * from pg_constraint where conname='t2_b_fkey' and conrelid='t2'::regclass;
-[ RECORD 1 ]-+----------
conname | t2_b_fkey
connamespace | 2200
contype | f
condeferrable | f
condeferred | f
convalidated | t
conrelid | 75202
contypid | 0
conindid | 75200
conparentid | 0
confrelid | 75194
confupdtype | a
confdeltype | a
confmatchtype | s
conislocal | t
coninhcount | 0
connoinherit | t
conkey | {2}
confkey | {1}
conpfeqop | {96}
conppeqop | {96}
conffeqop | {96}
conexclop |
conbin |
consrc |
postgres=#
convalidated 필드 의 값 은 t 입 니 다.이 외부 키 의 제약 이 유효 하 다 는 것 을 나타 냅 니 다.우리 가 다시 disable 을 사용 하 더 라 도 효과 적 인 것 으로 표 시 됩 니 다.
postgres=# alter table t2 disable trigger all;
ALTER TABLE
postgres=# select * from pg_constraint where conname='t2_b_fkey' and conrelid='t2'::regclass;
-[ RECORD 1 ]-+----------
conname | t2_b_fkey
connamespace | 2200
contype | f
condeferrable | f
condeferred | f
convalidated | t
conrelid | 75202
contypid | 0
conindid | 75200
conparentid | 0
confrelid | 75194
confupdtype | a
confdeltype | a
confmatchtype | s
conislocal | t
coninhcount | 0
connoinherit | t
conkey | {2}
confkey | {1}
conpfeqop | {96}
conppeqop | {96}
conffeqop | {96}
conexclop |
conbin |
consrc |
postgres=#
이것 은 우리 가(enable)내부 트리거 를 열 때 PostgreSQL 은(vaidate)제약 을 검증 하지 않 기 때문에 데이터 가 충돌 하 는 지 검증 하지 않 는 다 는 것 을 나타 낸다.왜냐하면 외부 키 제약 상태 가 항상 유효 하기 때문이다.우리 가 해 야 할 일 은 먼저 그것 을 무효 로 만 드 는 것 이다.
postgres=# alter table t2 alter CONSTRAINT t2_b_fkey not valid;
ERROR: ALTER CONSTRAINT statement constraints cannot be marked NOT VALID
## ,
postgres=# alter table t2 drop constraint t2_b_fkey;
ALTER TABLE
postgres=# delete from t2 where a in (3);
DELETE 1
postgres=# alter table t2 add constraint t2_b_fkey foreign key (b) references t1(a) not valid;
ALTER TABLE
postgres=# \d t2
Table "public.t2"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
a | integer | | not null |
b | integer | | |
c | text | | |
Indexes:
"t2_pkey" PRIMARY KEY, btree (a)
Foreign-key constraints:
"t2_b_fkey" FOREIGN KEY (b) REFERENCES t1(a) NOT VALID
이제 상태 가 무효 임 을 볼 수 있 습 니 다.
postgres=# select * from pg_constraint where conname='t2_b_fkey' and conrelid='t2'::regclass;
-[ RECORD 1 ]-+----------
conname | t2_b_fkey
connamespace | 2200
contype | f
condeferrable | f
condeferred | f
convalidated | f
conrelid | 75202
contypid | 0
conindid | 75200
conparentid | 0
confrelid | 75194
confupdtype | a
confdeltype | a
confmatchtype | s
conislocal | t
coninhcount | 0
connoinherit | t
conkey | {2}
confkey | {1}
conpfeqop | {96}
conppeqop | {96}
conffeqop | {96}
conexclop |
conbin |
consrc |
postgres=#
데이터 계속 삽입:
postgres=# insert into t2(a,b,c) values (3,3,'cc');
ERROR: insert or update on table "t2" violates foreign key constraint "t2_b_fkey"
DETAIL: Key (b)=(3) is not present in table "t1".
postgres=#
더 놀 라 셨 죠?잘못된 제약 조건 을 만 들 었 습 니 다.PostgreSQL 에 만 알 립 니 다.모든 줄 기록 이 효과 가 있 는 지 전체 표를 스 캔 하지 마 세 요.새로 삽입 되 거나 업 데 이 트 된 줄 에 대해 서 는 제약 조건 을 만족 시 키 는 지 확인 합 니 다.이것 이 바로 위 에 삽입 하 는 데 실 패 했 습 니 다.
우리 어떻게 해 야 되 지?
1.모든 외부 키 삭제
2.데이터 불 러 오기
3.외부 키 를 다시 만 들 지만 그 상 태 를 무효 로 설정 하여 전체 표를 스 캔 하지 않도록 합 니 다.이후 새로운 데이터 가 검 증 될 것 이다.
4.시스템 부하 가 적 을 때 제약 검증 시작(vaidate the constraints)
다른 방법 은:
postgres=# alter table t2 alter constraint t2_b_fkey deferrable;
ALTER TABLE
postgres=# begin;
BEGIN
postgres=# set constraints all deferred;
SET CONSTRAINTS
postgres=# insert into t2 (a,b,c) values (3,3,'cc');
INSERT 0 1
postgres=# insert into t2 (a,b,c) values (4,4,'dd');
INSERT 0 1
postgres=# insert into t1 (a,b,c) values (3,'cc',now());
INSERT 0 1
postgres=# insert into t1 (a,b,c) values (4,'dd',now());
INSERT 0 1
postgres=# commit;
COMMIT
이렇게 하 는 것 은 좋 지 않 은 점 은 다음 에 제출 할 때 만 작용 하기 때문에 모든 일 을 한 업무 에 맡 겨 야 한다.본 논문 의 관건 은 다음 의 가설 이 당신 의 데이터 가 틀 렸 다 는 것 을 검증 하 는 것 이다.
postgres=# alter table t2 disable trigger all;
ALTER TABLE
postgres=# insert into t2 (a,b,c) values (5,5,'ee');
INSERT 0 1
postgres=# alter table t2 enable trigger all;
ALTER TABLE
postgres=#
이것 은 새로운 데이터 만 검증 할 수 있 지만 모든 데이터 가 제약 을 만족 시 킬 수 있 는 것 은 아 닙 니 다.
postgres = # insert into t2 (a,b,c) values (6,6,'ff');
ERROR: insert or update on table "t2" violates foreign key constraint "t2_b_fkey"
DETAIL: Key(b) = (6) is not present in table "t1".
postgres = # select * from t2 where b = 5;
a | b | c
---+---+----
5 | 5 | ee
(1 row)
postgres = # select * from t1 where a = 5;
a | b | c
---+---+---
(0 rows)
최종 적 으로 해결 하 는 방법 이 있 습 니 다.pg 를 직접 수정 합 니 다.constraint 디 렉 터 리 표.하지만 사용자 에 게 이렇게 하 라 고 건의 합 니 다!
postgres=# delete from t2 where b = 5;
DELETE 1
postgres=# delete from t2 where b = 5;
DELETE 1
postgres=# alter table t2 disable trigger all;
ALTER TABLE
postgres=# insert into t2 values (5,5,'ee');
INSERT 0 1
postgres=# alter table t2 enable trigger all;
ALTER TABLE
postgres=# update pg_constraint set convalidated = false where conname = 't2_b_fkey' and conrelid = 't2'::regclass;
UPDATE 1
postgres=# alter table t2 validate constraint t2_b_fkey;
ERROR: insert or update on table "t2" violates foreign key constraint "t2_b_fkey"
DETAIL: Key (b)=(5) is not present in table "t1".
postgres=#
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.만약 잘못 이 있 거나 완전히 고려 하지 않 은 부분 이 있다 면 아낌없이 가르침 을 주시 기 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Redmine 데이터베이스를 MySQL에서 PostgreSQL로 마이그레이션 (보충)Redmine 의 Database 를 MySQL 로 운용하고 있었습니다만, MySQL 5.6 이상이나 MariaDB 에는 , , 이러한 티켓이 수년 동안 방치된 상황을 감안하여, PostgreSQL로 마이그레이션하기...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.