it-roy-ru.com

Невозможно добавить ограничение внешнего ключа - MySQL ERROR 1215 (HY000)

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

ERROR 1215 (HY000): Cannot add foreign key constraint

CREATE TABLE sales(
    saleId int(100) NOT NULL AUTO_INCREMENT,
    accountNo int(100) NOT NULL,
    payName VARCHAR(100) NOT NULL,
    nextPayment DATE,
    supplementName VARCHAR(250),
    qty int(11),
    workoutName VARCHAR(100),
    sDate datetime NOT NULL DEFAULT NOW(),
    totalAmount DECIMAL(11,2) NOT NULL,
    CONSTRAINT PRIMARY KEY(saleId, accountNo, payName),
    CONSTRAINT FOREIGN KEY(accountNo) REFERENCES accounts(accountNo) ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT FOREIGN KEY(payName) REFERENCES paymentFor(payName) ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT FOREIGN KEY(supplementName) REFERENCES supplements(supplementName) ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT FOREIGN KEY(workoutName) REFERENCES workouts(workoutName) ON DELETE CASCADE ON UPDATE CASCADE
);
    ALTER TABLE sales AUTO_INCREMENT = 2001;

Вот родительские таблицы.

CREATE TABLE accounts(
    accountNo int(100) NOT NULL AUTO_INCREMENT,
    accountType VARCHAR(100) NOT NULL,
    firstName VARCHAR(50) NOT NULL,
    lastName VARCHAR(60) NOT NULL,
    birthdate DATE NOT NULL,
    gender VARCHAR(7),
    city VARCHAR(50) NOT NULL,
    street VARCHAR(50),
    cellPhone VARCHAR(10),
    emergencyPhone VARCHAR(10),
    email VARCHAR(150) NOT NULL,
    description VARCHAR(350),
    occupation VARCHAR(50),
    createdOn datetime NOT NULL DEFAULT NOW(),
    CONSTRAINT PRIMARY KEY(accountNo)
);
    ALTER TABLE accounts AUTO_INCREMENT = 1001; 


CREATE TABLE supplements(
    supplementId int(100) NOT NULL AUTO_INCREMENT,
    supplementName VARCHAR(250) NOT NULL,
    manufacture VARCHAR(100),
    description VARCHAR(150),
    qtyOnHand INT(5),
    unitPrice DECIMAL(11,2),
    manufactureDate DATE,
    expirationDate DATE,
    CONSTRAINT PRIMARY KEY(supplementId, supplementName)
);
    ALTER TABLE supplements AUTO_INCREMENT = 3001;

CREATE TABLE workouts(
    workoutId int(100) NOT NULL AUTO_INCREMENT,
    workoutName VARCHAR(100) NOT NULL,
    description VARCHAR(7500) NOT NULL,
    duration VARCHAR(30),
    CONSTRAINT PRIMARY KEY(workoutId, workoutName)
);
    ALTER TABLE workouts AUTO_INCREMENT = 4001;



CREATE TABLE paymentFor(
    payId int(100) NOT NULL AUTO_INCREMENT,
    payName VARCHAR(100) NOT NULL,
    amount DECIMAL(11,2),
    CONSTRAINT PRIMARY KEY(payId, payName)
);
    ALTER TABLE paymentFor AUTO_INCREMENT = 5001;

Ребята, можете ли вы помочь мне с этой проблемой? Благодарю.

10
Dhanuka

Чтобы поле было определено как foreign key, родительское поле, на которое ссылаются, должно иметь определенный индекс.

Согласно документации по ограничениям foreign key

ССЫЛКИ parent_tbl_name (index_col_name, ...)

Определите INDEX для workouts.workoutName, paymentFor.paymentName и supplements.supplementName соответственно. И убедитесь, что определения дочерних столбцов должны совпадать с определениями их родительских столбцов. 

Измените определение таблицы workouts, как показано ниже: 

CREATE TABLE workouts(
    workoutId int(100) NOT NULL AUTO_INCREMENT,
    workoutName VARCHAR(100) NOT NULL,
    description VARCHAR(7500) NOT NULL,
    duration VARCHAR(30),

    KEY ( workoutName ), -- <---- this is newly added index key

    CONSTRAINT PRIMARY KEY(workoutId, workoutName)
);

Измените определение таблицы supplements, как показано ниже: 

CREATE TABLE supplements(
    supplementId int(100) NOT NULL AUTO_INCREMENT,
    supplementName VARCHAR(250) NOT NULL,
    manufacture VARCHAR(100),
    description VARCHAR(150),
    qtyOnHand INT(5),
    unitPrice DECIMAL(11,2),
    manufactureDate DATE,
    expirationDate DATE,

    KEY ( supplementName ), -- <---- this is newly added index key

    CONSTRAINT PRIMARY KEY(supplementId, supplementName)
);

Измените определение таблицы paymentFor, как показано ниже: 

CREATE TABLE paymentFor(
    payId int(100) NOT NULL AUTO_INCREMENT,
    payName VARCHAR(100) NOT NULL,
    amount DECIMAL(11,2),

    KEY ( payName ), -- <---- this is newly added index key

    CONSTRAINT PRIMARY KEY(payId, payName)
);

Теперь измените определение дочерней таблицы, как показано ниже: 

CREATE TABLE sales(
    saleId int(100) NOT NULL AUTO_INCREMENT,
    accountNo int(100) NOT NULL,
    payName VARCHAR(100) NOT NULL,
    nextPayment DATE,
    supplementName VARCHAR(250) NOT NULL,
    qty int(11),
    workoutName VARCHAR(100) NOT NULL,
    sDate datetime NOT NULL DEFAULT NOW(),
    totalAmount DECIMAL(11,2) NOT NULL,
    CONSTRAINT PRIMARY KEY(saleId, accountNo, payName),
    CONSTRAINT FOREIGN KEY(accountNo) 
       REFERENCES accounts(accountNo) 
       ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT FOREIGN KEY(payName) 
       REFERENCES paymentFor(payName) 
       ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT FOREIGN KEY(supplementName) 
       REFERENCES supplements(supplementName) 
       ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT FOREIGN KEY(workoutName) 
       REFERENCES workouts(workoutName) 
       ON DELETE CASCADE ON UPDATE CASCADE
);

Ссылаться на

[ОГРАНИЧЕНИЕ [символ]] ИНОСТРАННЫЙ КЛЮЧ
[index_name] (index_col_name, ...)
ССЫЛКИ tbl_name (index_col_name, ...)
[ON DELETE reference_option]
[НА ОБНОВЛЕНИИ reference_option] 

reference_option:
ОГРАНИЧЕНИЕ | КАСКАД | SET NULL | БЕЗДЕЙСТВИЕ 

20
Ravinder Reddy

Если вы когда-нибудь захотите выяснить, почему возникла эта ошибка, все, что вам нужно сделать, - это запустить команду ниже и найти « LATEST FOREIGN KEY ERROR »

Команда для запуска: -

mysql> SHOW ENGINE INNODB STATUS

Вы будете знать причину ваших таких ошибок.

29
John Cargo

Внешние ключи - это способ реализации отношений/ограничений между столбцами в разных таблицах.

Существуют различные категории ограничений, которые влияют на их применение при обновлении или удалении строки из родительской таблицы:

VarCascade: Если строка удаляется из родительской, то все строки в дочерней таблице с соответствующим значением FK также будут удалены. Аналогично для изменений значения в родительской таблице.

VarRestrict: Строка не может быть удалена из родительской таблицы, если это нарушит ограничение FK для дочерней таблицы. Аналогично для изменений значения в родительской таблице.

CodeNo Action: очень похоже на «Restrict», за исключением того, что любые события/триггеры в родительской таблице будут выполняться до того, как ограничение будет применено, предоставляя разработчику приложения возможность разрешать любые конфликты ограничений FK с помощью хранимой процедуры.

CodeSet NULL: если значение NULL является допустимым значением для столбца FK в дочерней таблице, тогда оно будет установлено в NULL, если связанные данные в родительской таблице обновлены или удалены.

CodeSet Default: если в дочерней таблице есть значение по умолчанию для столбца FK, оно будет использовано, если связанные данные в родительской таблице обновлены или удалены. Обратите внимание, что это не реализовано в этой версии - ограничение может быть добавлено в схему, но любое последующее удаление или обновление столбца в родительской таблице завершится неудачно.

4
user4757271

Иногда вы получаете эту ошибку "# 1215 - Невозможно добавить ограничение внешнего ключа" из-за несоответствия таблицы TYPE (InnoDB, MyISAM, ..).

Поэтому измените тип таблицы на тот же и попробуйте применить ограничение внешнего ключа

mysql> ALTER TABLE table_name ENGINE=InnoDB;

mysql> ALTER TABLE Orders ADD FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)

3
kadhiresan k

Это может работать для некоторых людей. Просто добавьте набор символов по умолчанию как utf8

DEFAULT CHARACTER SET = utf8;
2
edem

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

Таблицы, созданные с помощью утилиты создания таблиц MySQL Workbench, имеют латинскую кодировку по умолчанию.

Простой способ выяснить это, если вы используете верстак, - это просмотреть оператор создания таблицы для любой таблицы. У вас будет строка кодировки по умолчанию в конце.

1
Divije Narasimhachar

Я не отвечаю на вышеупомянутый вопрос, но только для людей, которые столкнутся с той же самой ошибкой mysql.

Все, что я сделал, это поменял ссылочный движок таблицы на innodb.

0
Peter

Я сталкиваюсь с этой ошибкой: я добавляю ограничение внешнего ключа для столбца, который имеет «не нулевое ограничение», но я указал «при удалении set null» в внешнем ограничении. Это противоречие, которое поначалу может быть неочевидным.

Вот мои две таблицы:

CREATE TABLE study (
    id int(11) NOT NULL AUTO_INCREMENT primary key,
    name varchar(100) NOT NULL,
    introduction text,
    objective varchar(250) DEFAULT NULL,
    method text,
    result text,
    conclusion varchar(250) DEFAULT NULL,
    future_action varchar(100) DEFAULT NULL
);

drop table client_study;
CREATE TABLE client_study (
      id int(11) NOT NULL AUTO_INCREMENT primary key,
      client_id int(11),
      study_id int(11) not null, --If delete 'not null' error goes away!
      contact_person int(11),
      effective_date datetime DEFAULT CURRENT_TIMESTAMP,
      trial_site int(11) DEFAULT NULL,
      UNIQUE KEY unqidx_client_study (client_id,study_id)
);

ALTER TABLE client_study
ADD CONSTRAINT FOREIGN KEY (study_id) REFERENCES study(id)
ON DELETE SET NULL ON UPDATE CASCADE;

ERROR 1215 (HY000): Cannot add foreign key constraint

Если вы удалите ограничение NOT NULL для столбца study_id в таблице client_study, можно добавить внешний ключ. Другой альтернативой является сохранение ограничения not null для client_table, но изменение определения внешнего ключа для удаления без действия или других вариантов.

0
Kemin Zhou