Mysql и проблема FK - PullRequest
       8

Mysql и проблема FK

1 голос
/ 10 сентября 2011

У меня проблемы с некоторыми таблицами.

У меня есть эта таблица:

CREATE TABLE `smenuitem` (
    `nome` VARCHAR(150) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `url` VARCHAR(150) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `tipo` CHAR(4) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `ordemmenu` INT(10) NULL DEFAULT NULL,
    `codparent` INT(10) UNSIGNED NOT NULL,
    `codmenuitem` INT(10) UNSIGNED NOT NULL,
    `codmodulo` INT(10) UNSIGNED NOT NULL,
    PRIMARY KEY (`codmodulo`, `codmenuitem`, `codmenuitem2`),
    CONSTRAINT `FK_smenuitem_smodulos` FOREIGN KEY (`codmodulo`) REFERENCES `smodulos` (`codmodulo`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT

И вторая:

CREATE TABLE `smenuitememp` (
    `codempresa` INT(10) UNSIGNED NOT NULL,
    `codmodulo` INT(10) UNSIGNED NOT NULL,
    `codmenuitem` INT(10) UNSIGNED NOT NULL,
    PRIMARY KEY (`codmenuitem`, `codempresa`, `codmodulo`)
)
COLLATE='utf8_unicode_ci'

Моя проблема, этоМне нужно сделать FK между codmenuitem У меня есть эта команда sql, которые приводят к ошибке:

ALTER TABLE `smenuitememp`  ADD CONSTRAINT `FK_smenuitememp_smenuitem` FOREIGN KEY (`codmenuitem`) REFERENCES `smenuitem` (`codmenuitem`);

Когда я пытаюсь выполнить, он возвращает эту ошибку:

enter image description here

У кого-то есть идея?


Обновление ... Я пытался решить проблему и получил новый вопрос ... T_T

CREATE TABLE `smenuitem` (
    `nome` VARCHAR(150) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `url` VARCHAR(150) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `tipo` CHAR(4) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `ordemmenu` INT(10) NULL DEFAULT NULL,
    `codparent` INT(10) UNSIGNED NOT NULL,
    `codmenuitem` INT(10) UNSIGNED NOT NULL,
    `codmodulo` INT(10) UNSIGNED NOT NULL,
    PRIMARY KEY (`codmodulo`, `codmenuitem`),
    INDEX `codmenuitem` (`codmenuitem`),
    CONSTRAINT `FK_smenuitem_smodulos` FOREIGN KEY (`codmodulo`) REFERENCES `smodulos` (`codmodulo`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT

Я решилпроблема создания индекса на главной таблице.Но я не знаю, почему у меня были проблемы без этого индекса.Если бы кто-то мог спросить меня, я бы оценил!

1 Ответ

2 голосов
/ 10 сентября 2011

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

Другими словами, следующие примеры работают в InnoDB:

CREATE TABLE Foo ( a INT, b INT, c INT, PRIMARY KEY (a,b,c) );
CREATE TABLE Bar ( x INT, y INT );

ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(b,c); -- WRONG

ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(a,c); -- WRONG

ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(a,b); -- RIGHT

ALTER TABLE Bar ADD FOREIGN KEY (x) REFERENCES Foo(b); -- WRONG

ALTER TABLE Bar ADD FOREIGN KEY (x) REFERENCES Foo(a); -- RIGHT

Вы получили ошибку, потому что пытаетесь сделать эквивалент (x) ссылок Foo (b).
Ваш столбец codmenuitem является вторым из трех столбцов в первичном ключе родителя.

Это сработало бы, если бы smenuitememp.codemenuitem ссылалось на smenuitem.codmodulo, поскольку этот столбец является крайним левым столбцом в родительской таблице.первичный ключ.


Повторяйте свой следующий вопрос:

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

Если вы попытаетесь найти строкуна основе среднего столбца многостолбцового индекса индекс вам не поможет.По аналогии это похоже на поиск в телефонной книге всех людей с определенным отчеством.

Стандартный ANSI SQL требует, чтобы указанный столбец был частью PRIMARY KEY или UNIQUE KEY, а также чтобы столбцы внешнего ключасопоставьте все столбцы первичного или уникального ограничения в родительском элементе.

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

Это может привести к странным случаям, таким как дочерняя строка, которая ссылается на более чем одну строку в родительском элементе, но ожидается, что вы будете обрабатывать такие аномалии.


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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...