MySQL Composite PK com anuláveis ??FKs
-
22-07-2019 - |
Pergunta
Primeiro, deixe-me começar esta questão, afirmando que eu sou realmente um muito terrível modelador de dados. Eu sei apenas o suficiente para ser perigoso.
A tabela que estou construindo tem quatro chaves estrangeiras, duas das quais fazem referência à mesma mesa. Aqui está a declaração criar para essa tabela.
CREATE TABLE IF NOT EXISTS `abnr`.`reputation_event_log` (
`id` INT NOT NULL AUTO_INCREMENT ,
`reputation_event_id` INT NULL ,
`giver_user_id` INT NULL ,
`receiver_user_id` INT NULL ,
`review_id` INT NULL ,
`giver_point_value` SMALLINT NULL DEFAULT 0 ,
`receiver_point_value` SMALLINT NULL DEFAULT 0 ,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY (`id`) ,
INDEX `fk_reputation_log_user` (`giver_user_id` ASC) ,
INDEX `fk_reputation_log_user1` (`receiver_user_id` ASC) ,
INDEX `fk_reputation_log_review` (`review_id` ASC) ,
INDEX `fk_reputation_log_reputation_event` (`reputation_event_id` ASC) ,
CONSTRAINT `fk_reputation_log_user`
FOREIGN KEY (`giver_user_id` )
REFERENCES `abnr`.`user` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_reputation_log_user1`
FOREIGN KEY (`receiver_user_id` )
REFERENCES `abnr`.`user` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_reputation_log_review`
FOREIGN KEY (`review_id` )
REFERENCES `abnr`.`review` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_reputation_log_reputation_event`
FOREIGN KEY (`reputation_event_id` )
REFERENCES `abnr`.`reputation_event` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
Os índices eu estou preocupado com para este post são fk_reputation_log_user
e fk_reputation_log_user1
. Cada evento reputação tem um doador, mas apenas alguns têm um receptor. Eu faria como este FK ser anulável, mas eu não sei como fazer isso, ou se é mesmo "permitido".
Eu também brincou com a idéia de fazer tudo o FK colunas parte da chave primária para ter proteção em nível de banco de dados contra entradas de log duplicadas -. Mas isso não vai trabalho desde colunas PK tem que ser NOT NULL
Se você precisar de mais detalhes, por favor, estado que nos comentários. Obrigado!
(Sim, este é um sistema de reputação não muito diferente do que isso tem)
Solução
CREATE TABLE IF NOT EXISTS `abnr`.`reputation_event_log` (
`id` INT NOT NULL AUTO_INCREMENT ,
`reputation_event_id` INT NULL ,
`giver_user_id` INT NOT NULL , -- mandatory giver_user_id
`receiver_user_id` INT NULL , -- optional receiver_user_id
. . .
Sim, você pode ter NULL
em uma coluna com uma restrição de chave estrangeira declarou sobre ele. A restrição NOT NULL
numa coluna é independente de qualquer chave estrangeira constrangimento (s) em que a coluna.
Um meio de chaves estrangeiras que se a coluna tem um valor diferente de NULL, em seguida, esse valor deve existir na chave primária da tabela referenciada pela restrição de chave estrangeira.
Editar: Quanto à sua exigência UNIQUE
, você está ciente que você pode declarar uma restrição UNIQUE
em colunas anuláveis. A coluna pode conter NULL
s (ao contrário da restrição de chave primária). Este é o comportamento padrão SQL, e é suportado pelo MySQL.
. . .
PRIMARY KEY (`id`),
CONSTRAINT UNIQUE (`giver_user_id`, `receiver_user_id`,
`review_id`, `reputation_event_id`),
. . .