2010-01-14 3 views
1

온라인 SQL 빌더를 사용하여 제가 작업중인 일부 MySQL 테이블을 디자인하는 데 도움이되었습니다. 외래 키는 항상 나를 혼란스럽게합니다.이러한 외래 키는 어떤 기능을 수행합니까?

이 4 가지 외래 키를 추가하려고했지만 내가 추가하기 전에이를 확인하려고합니다.

ALTER TABLE `users` ADD FOREIGN KEY (user_id) REFERENCES `settings` (`user_id`); 
ALTER TABLE `logins` ADD FOREIGN KEY (user_id) REFERENCES `users` (`user_id`); 
ALTER TABLE `mail_threads` ADD FOREIGN KEY (folder_id) REFERENCES `mail_folders` (`folder_id`); 
ALTER TABLE `mail_message` ADD FOREIGN KEY (thread_id) REFERENCES `mail_threads` (`thread_id`); 

그래서 기본적으로 무엇을 제한합니까? 아래의 표 4 개 모두, 나는 그것들에 외래 키를 사용해서는 안되며, 다른 것들을 망칠 필요없이 개별적으로 업데이트 할 수 있어야합니다.

+0

외래 키는 선택 사항이 아닙니다. 그것들은 당신의 도메인 관계의 일부입니다. –

+1

MyISAM을 테이블 형식으로 사용하는 경우에는 현재 외부 키 선언이 무시됩니다. 현재 외래 키 제약 조건을 위해 InnoDB가 필요합니다 (MyISAM에 대한 외래 키 지원은 작동해야합니다). –

답변

1

외부 키는 데이터베이스가 '부모'테이블에 연결을 할당하는 방법입니다.

목록의 맨 아래에서부터 시작하여 내 방식대로 작업하겠습니다.

바닥 FK 컬럼 mail_message.thread_idmail_threads.thread_id 다음 FK 참조가 열 mail_threads.folder_id 이것이 mail_thread가 mail_folder "에 속하는"이다 의미 mail_folders.folder_id

참조임을 주장하고, 그 상태 mail_message는 mail_thread에 "속합니다". 따라서 thread_id가 20 인 mail_thread가없는 경우 thread_id가 20 인 mail_message를 만들 수 없습니다. 의미가 없으므로 (참조가 작동하지 않기 때문에) mail_message를 20으로 만들 수 없습니다. 또한 thread_id 20의 mail_thread를 지우지 못하도록합니다. 삭제를 계단식으로 처리하지 않고 (제약 조건을 통해 관련된 모든 항목의 삭제를 강제로 수행하지 않고) 해당 스레드 내에 메시지가 있거나 메시지를 먼저 삭제하지 못하게합니다. 간단히 말해서

,이 두 제약 말 :
mail_messages이 mail_folders에 속하는 mail_threads에 속하는
- 또는
mail_folders이

이 그래서 함께 질문 많은 mail_messages 제로가 많은 mail_threads 제로 혜택/FK의 함정 :
What's wrong with foreign keys?

0

외래 키는 단순히 개체 무결성을 그대로 유지합니다. 동일한 사용자 ID를 가진 행이 settings에 없으면이 코드는 사용자 ID를 변경할 수 없습니다. 해당 사용자가없는 경우 logins 테이블에서 사용자 ID를 변경할 수 없습니다. 기타

테이블을 "어지럽히는"것은 무엇을 의미합니까? 모든 사용자가 항상 해당 설정 행을 가지고있는 한 settings 테이블을 업데이트하지 않고 언제든지 users 테이블을 업데이트 할 수 있습니다. 그렇지 않으면 쿼리가 실패합니다.

중요한 이유가있는 경우가 아니면 코드를 그대로 두십시오. 외래 키 제약이 당신의 방식대로 발생한다면, 그것은 당신의 코드가 잘못된 것을하고 있다는 것을 알리는 것일뿐입니다.

1

외래 키는 존재하지 않는 레코드에 대한 참조를 작성하지 않도록합니다. 외래 키에 의해 생성 된 제약 조건은 종종 데이터베이스에서 데이터 무결성을 시행하는 근본적인 것으로 간주됩니다. 사실

나는 다음과 같이 첫 번째 외부 키를 쥐게 될 필요가있다 생각한다

ALTER TABLE `settings` ADD FOREIGN KEY (user_id) REFERENCES `users` (`user_id`); 

이 테이블 settings의 모든 user_idusers 테이블에 이미 존재하는 유효한 user_id 될 것이라는 점을 보장 할 것이다. 또한 settings 테이블에 여전히 삭제할 사용자를 참조하는 행이있는 경우 users 테이블의 행을 삭제할 수 없습니다. 따라서 고아 행이 없도록합니다.

원본 외래 키는 사용자 행 앞에 삽입 할 설정 행을 필요로했을 것입니다. 사용자 행이 의도하지 않았다고 생각됩니다. 이 외부 키는 users 테이블에서 새 사용자를 허용하기 전에 settings 테이블에서 user_id을 확인합니다. 다음 외래 키에 관해서는

:

ALTER TABLE `logins` ADD FOREIGN KEY (user_id) REFERENCES `users` (`user_id`); 

이 것 또한 테이블 logins의 모든 user_idusers 테이블에 이미 존재하는 유효한 user_id을 보장합니다. 테이블 usersuser_id = 100의 사용자가없는 경우 데이터베이스는 logins 테이블에 user_id = 100이라는 레코드를 허용하지 않습니다.

당신은 이미 mail_folders 테이블 INT 현재, 유효한 thread_id 필요 mail_message 제약에 대해 동일한 folder_id를 필요로하는 mail_threads 제약, 동일한 논리를 적용 할 수 있습니다.

+0

외래 키의 목표가 설정 행을 절대 포기하지 않도록하려면 변경해야합니다. 그러나 코드가 설정 행이없는 사용자가 없는지 확인하려는 경우가 많습니다.이 경우 기존 코드가 의미가 있습니다. – Matchu

+0

'settings' 행이'users' 행 앞에 삽입 될 필요가 없습니까? 이 외래 키는'settings' 테이블에서'user_id'를 검사하기 전에'users' 테이블에서 새로운 사용자를 허용합니다. –

관련 문제