114

PostgreSQL 8에서는 다음 표의 두 외래 키에 "on delete cascades"를 추가 할 수 있습니까? 여기"삭제 캐스케이드"제약 조건을 추가하는 방법은 무엇입니까?

# \d pref_games 
            Table "public.pref_games" 
    Column |   Type    |      Modifiers 
----------+-----------------------------+---------------------------------------------------------- 
gid  | integer      | not null default nextval('pref_games_gid_seq'::regclass) 
rounds | integer      | not null 
finished | timestamp without time zone | default now() 
Indexes: 
    "pref_games_pkey" PRIMARY KEY, btree (gid) 
Referenced by: 
    TABLE "pref_scores" CONSTRAINT "pref_scores_gid_fkey" FOREIGN KEY (gid) REFERENCES pref_games(gid) 

그리고 :

# \d pref_users 
       Table "public.pref_users" 
    Column |   Type    | Modifiers 
------------+-----------------------------+--------------- 
id   | character varying(32)  | not null 
first_name | character varying(64)  | 
last_name | character varying(64)  | 
female  | boolean      | 
avatar  | character varying(128)  | 
city  | character varying(64)  | 
login  | timestamp without time zone | default now() 
last_ip | inet      | 
logout  | timestamp without time zone | 
vip  | timestamp without time zone | 
mail  | character varying(254)  | 
Indexes: 
    "pref_users_pkey" PRIMARY KEY, btree (id) 
Referenced by: 
    TABLE "pref_cards" CONSTRAINT "pref_cards_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 
    TABLE "pref_catch" CONSTRAINT "pref_catch_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 
    TABLE "pref_chat" CONSTRAINT "pref_chat_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 
    TABLE "pref_game" CONSTRAINT "pref_game_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 
    TABLE "pref_hand" CONSTRAINT "pref_hand_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 
    TABLE "pref_luck" CONSTRAINT "pref_luck_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 
    TABLE "pref_match" CONSTRAINT "pref_match_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 
    TABLE "pref_misere" CONSTRAINT "pref_misere_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 
    TABLE "pref_money" CONSTRAINT "pref_money_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 
    TABLE "pref_pass" CONSTRAINT "pref_pass_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 
    TABLE "pref_payment" CONSTRAINT "pref_payment_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 
    TABLE "pref_rep" CONSTRAINT "pref_rep_author_fkey" FOREIGN KEY (author) REFERENCES pref_users(id) 
    TABLE "pref_rep" CONSTRAINT "pref_rep_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 
    TABLE "pref_scores" CONSTRAINT "pref_scores_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 
    TABLE "pref_status" CONSTRAINT "pref_status_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 

그리고 그것은 이전 테이블에 2 index'es를 추가하는 것이 합리적 경우도 궁금 여기 -

# \d pref_scores 
     Table "public.pref_scores" 
Column |   Type   | Modifiers 
---------+-----------------------+----------- 
id  | character varying(32) | 
gid  | integer    | 
money | integer    | not null 
quit | boolean    | 
last_ip | inet     | 
Foreign-key constraints: 
    "pref_scores_gid_fkey" FOREIGN KEY (gid) REFERENCES pref_games(gid) 
    "pref_scores_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) 

모두 참조 테이블은 다음과 같습니다 ?

UPDATE : 감사합니다, 또한 내가 필요를 따라서 트랜잭션 내가 한 성명에서 그것을 관리 할 수 ​​있다는, 메일 링리스트의 조언을 얻지 및했습니다

ALTER TABLE public.pref_scores 
DROP CONSTRAINT pref_scores_gid_fkey, 
ADD CONSTRAINT pref_scores_gid_fkey 
    FOREIGN KEY (gid) 
    REFERENCES pref_games(gid) 
    ON DELETE CASCADE; 
+1

약간의 OT이지만, 참조하는 열 (예 :'pref_scores.gid')에 색인을 생성하지 않았다는 것을 알았습니다. 이러한 테이블에 많은 행이 있으면 참조 된 테이블의 삭제에 시간이 오래 걸릴 것입니다. 일부 데이터베이스는 참조하는 열 (들)에 대한 색인을 자동으로 작성합니다. PostgreSQL은 가치가없는 경우가 있기 때문에 여러분에게 맡깁니다. – kgrittn

+1

감사합니다! 실제로 delete의 시간이 오래 걸리는 것을 알았지 만 그 이유를 알지 못했습니다 –

+1

외장형 키의 인덱스가 가치가없는 경우 어떤 경우입니까? –

답변

144

내가 꽤 있어요을 기존 외래 키 제약 조건에 단순히 on delete cascade을 추가 할 수는 없습니다. 먼저 제약 조건을 삭제 한 다음 올바른 버전을 추가해야합니다. 표준 SQL에서는, 나는

  • on delete cascade와 외부 키를 추가,
  • 는 외래 키를 드롭,이 작업을 수행하는 가장 쉬운 방법은 트랜잭션을 시작
    • 로 믿고, 그리고 마지막으로
    • 는 트랜잭션을 커밋

    변경할 각 외래 키에 대해 반복하십시오.

    그러나 PostgreSQL에는 단일 SQL 문에서 여러 개의 제약 조건 절을 사용할 수있는 비표준 확장이 있습니다. 당신이 드롭 할 외래 키 제약 조건의 이름을 모르는 경우 예를 들어

    alter table public.pref_scores 
    drop constraint pref_scores_gid_fkey, 
    add constraint pref_scores_gid_fkey 
        foreign key (gid) 
        references pref_games(gid) 
        on delete cascade; 
    

    , 당신이 pgAdminIII에서 그것을 찾아 볼 수 있습니다 (단 테이블 이름을 클릭하고 DDL을보고, 또는 확장 계층 구조가 "제약 조건"을 찾을 때까지) 또는 query the information schema 수 있습니다.

    select * 
    from information_schema.key_column_usage 
    where position_in_unique_constraint is not null 
    
  • +0

    고마워요, 그게 제가 생각한 것입니다 -하지만 외래 키들과 어떻게해야합니까? 그들은 쉽게 떨어 뜨리고 읽을 수있는 제약 조건 (NOT NULL과 유사)입니까? –

    +2

    @AlexanderFarber : 그렇습니다. 이름을 지우고 쉽게 추가 할 수 있습니다. 그러나 당신은 아마 거래 내에서 그렇게하기를 원할 것입니다. 내 대답을 세부 사항으로 업데이트했습니다. –

    +0

    +1 for pgAdminIII. DROP CONSTRAINT 및 ADD CONSTRAINT 명령을 제공하기 때문에 쿼리 창에 복사하여 붙여 넣기 만하면 원하는대로 명령을 편집 할 수 있습니다. –

    3

    사용법 :

    select replace_foreign_key('user_rates_posts', 'post_id', 'ON DELETE CASCADE'); 
    

    기능 :

    CREATE OR REPLACE FUNCTION 
        replace_foreign_key(f_table VARCHAR, f_column VARCHAR, new_options VARCHAR) 
    RETURNS VARCHAR 
    AS $$ 
    DECLARE constraint_name varchar; 
    DECLARE reftable varchar; 
    DECLARE refcolumn varchar; 
    BEGIN 
    
    SELECT tc.constraint_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name 
    FROM 
        information_schema.table_constraints AS tc 
        JOIN information_schema.key_column_usage AS kcu 
         ON tc.constraint_name = kcu.constraint_name 
        JOIN information_schema.constraint_column_usage AS ccu 
         ON ccu.constraint_name = tc.constraint_name 
    WHERE constraint_type = 'FOREIGN KEY' 
        AND tc.table_name= f_table AND kcu.column_name= f_column 
    INTO constraint_name, reftable, refcolumn; 
    
    EXECUTE 'alter table ' || f_table || ' drop constraint ' || constraint_name || 
    ', ADD CONSTRAINT ' || constraint_name || ' FOREIGN KEY (' || f_column || ') ' || 
    ' REFERENCES ' || reftable || '(' || refcolumn || ') ' || new_options || ';'; 
    
    RETURN 'Constraint replaced: ' || constraint_name || ' (' || f_table || '.' || f_column || 
    ' -> ' || reftable || '.' || refcolumn || '); New options: ' || new_options; 
    
    END; 
    $$ LANGUAGE plpgsql; 
    

    가주의 :이 기능 초기 외부 키의 특성을 복사하지 않습니다. 외부 테이블 이름/열 이름 만 사용하고 현재 키는 삭제하고 을 새로운 것으로 바꿉니다.