2

Прежде всего, позвольте мне предисловие к этому вопросу, заявив, что я действительно очень страшный модератор данных. Я знаю только достаточно, чтобы быть опасным.MySQL Composite PK с Nullable FKs

В таблице, в которой я строим, есть четыре внешних ключа, два из которых относятся к одной и той же таблице. Вот инструкция create для этой таблицы.

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; 

Индексы я озабочен на этот пост являются fk_reputation_log_user и fk_reputation_log_user1. У каждого события репутации есть даритель, но только у некоторых есть получатель. Я бы как этот FK был нулевым, но я не знаю, как это сделать, или если он даже «разрешен».

Я также играл с идеей сделать все столбцы FK частью первичного ключа для защиты на уровне базы данных от дублированных записей журнала, но это не сработает, поскольку столбцы PK должны быть NOT NULL.

Если вам нужно больше деталей, пожалуйста, укажите это в комментариях. Благодаря!

(Да, это для системы репутации не слишком отличающемся от того, что ТАК)

ответ

4
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 
    . . . 

Да, вы можете иметь NULL в колонке с ограничением внешнего ключа объявленной на нем. Ограничение NOT NULL для столбца не зависит от ограничений внешнего ключа в этом столбце.

Внешний ключ означает, что , если, столбец имеет значение, отличное от NULL, то это значение должно существовать в первичном ключе таблицы, на которое ссылается ограничение внешнего ключа.

редактировать: Что касается вашего UNIQUE требования, вы в курсе, что вы можете объявить UNIQUE ограничения на обнуляемых столбцах. Столбец может содержит NULL s (в отличие от ограничения первичного ключа). Это стандартное поведение SQL и поддерживается MySQL.

. . . 
    PRIMARY KEY (`id`), 
    CONSTRAINT UNIQUE (`giver_user_id`, `receiver_user_id`, 
        `review_id`, `reputation_event_id`), 
    . . . 
+0

Я не знал об этом, но большое вам спасибо за помощь! – 2008-12-02 19:31:06