Introdução
Condições para usar chaves estrangeiras:
- As duas tabelas devem ser tabelas InnoDB, tabelas MyISAM não suportam chaves estrangeiras temporariamente
- A coluna da chave estrangeira deve ser indexada, MySQL 4.1.2 e versões posteriores irão criar automaticamente o índice quando a chave estrangeira for criada
- As colunas das duas tabelas da relação de chave estrangeira devem ser de tipos de dados semelhantes, ou seja, colunas que podem ser convertidas entre si, como int e tinyint, mas não int e char, e os campos associados devem ser exclusivos
Quatro tipos de restrições de chave estrangeira
RESTRICT (restrição): Se aparecer durante a exclusão, significa que a chave primária de chave estrangeira foi gravada (registro na tabela primária) não pode ser excluída diretamente. Você deve excluir todas as chaves primárias de chave estrangeira no campo dept_id da tabela restrita (da tabela). O registro correspondente ao valor pode excluir a restrição de chave estrangeira (o registro na tabela principal) .O teste constatou que a configuração padrão não está selecionada no Navicat.
NO ACTION: Equivale a RESTRICT no MySQL. O motivo é o seguinte: restringir é verificar se há dados correspondentes na tabela antes de modificar ou excluir. Se houver, rejeite a operação, e nenhuma ação é o sql padrão de origem em alguns bancos de dados , Irá atrasar a verificação, ou seja, verificar se há dados correspondentes na tabela escrava após modificação ou exclusão, se houver, rejeitar a operação, mas no MySQL, as restrições de chave estrangeira serão verificadas imediatamente, então as duas são equivalentes
CASCADE: Excluir Quando esta opção é selecionada, quando o registro na tabela primária é excluído, o registro com o valor de id da tabela secundária associado ao id da chave primária na tabela primária também será excluído. Recomenda-se não escolher.
SET NULL: Ao excluir esta opção, se o valor do campo restrito da tabela (na tabela onde o campo restrito está localizado) for definido como anulável, então quando o registro da tabela principal for excluído, aquele da tabela principal será excluído O valor da chave primária correspondente ao registro (o valor do campo da tabela escrava restrita) aparece no campo correspondente na tabela escrava, e o valor do campo restrito do registro se tornará NULL.
O mais comumente usado é selecionar a restrição de que RESTRICT não permite exclusão ou selecionar SET NULL para excluir a tabela de valores para ficar vazia.
Exemplo
Etapa 1: crie duas tabelas: tabela de departamento dept e tabela de funcionários emp, e associe a chave estrangeira de emp.dno a dept.did
CREATE TABLE `dept` (
`did` int(10) NOT NULL AUTO_INCREMENT,
`dname` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`did`),
UNIQUE KEY `dname` (`dname`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `emp` (
`eid` int(10) NOT NULL AUTO_INCREMENT,
`ename` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
`dno` int(10) DEFAULT NULL,
`sal` double(7,2) DEFAULT NULL,
PRIMARY KEY (`eid`),
KEY `fk_dno_did` (`dno`),
CONSTRAINT `fk_dno_did` FOREIGN KEY (`dno`) REFERENCES `dept` (`did`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
mysql> desc dept;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| did | int(10) | NO | PRI | NULL | auto_increment |
| dname | varchar(255) | NO | UNI | NULL | |
+-------+--------------+------+-----+---------+----------------+
mysql> desc emp;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| eid | int(10) | NO | PRI | NULL | auto_increment |
| ename | varchar(30) | YES | | NULL | |
| dno | int(10) | YES | MUL | NULL | |
| sal | double(7,2) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
Etapa 2: inicializar os dados da tabela
insert into dept values (1,'技术部'),(2,'人事部');
insert into emp values (1,'张三',1,10000),(2,'李四',2,20000);
mysql> select * from dept order by did;
+-----+--------+
| did | dname |
+-----+--------+
| 1 | 技术部 |
| 2 | 人事部 |
+-----+--------+
mysql> select * from emp order by eid;
+-----+-------+-----+----------+
| eid | ename | dno | sal |
+-----+-------+-----+----------+
| 1 | 张三 | 1 | 10000.00 |
| 2 | 李四 | 2 | 20000.00 |
+-----+-------+-----+----------+
Etapa 3: quando houver dados associados, exclua ou atualize a tabela de dados do departamento, ou reporte um erro ao inserir ou atualizar emp (quatro casos)
delete from dept where did=1;
1451 - Cannot delete or update a parent row: a foreign key constraint fails (`test`.`emp`, CONSTRAINT `fk_dno_did` FOREIGN KEY (`dno`) REFERENCES `dept` (`did`))
update dept set did=3 where did=1;
1451 - Cannot delete or update a parent row: a foreign key constraint fails (`test`.`emp`, CONSTRAINT `fk_dno_did` FOREIGN KEY (`dno`) REFERENCES `dept` (`did`))
insert into emp values (null,'张三',4,10000);
1452 - Cannot add or update a child row: a foreign key constraint fails (`test`.`emp`, CONSTRAINT `fk_dno_did` FOREIGN KEY (`dno`) REFERENCES `dept` (`did`))
update emp set dno=3 where eid=1;
1452 - Cannot add or update a child row: a foreign key constraint fails (`test`.`emp`, CONSTRAINT `fk_dno_did` FOREIGN KEY (`dno`) REFERENCES `dept` (`did`))
Extensão: outros tipos de restrição
- Restrição de chave primária PRIMARY KEY
- ÚNICO
- Restrição não NULL
- Restrição de valor padrão DEFAULT