Отбрасывать внешний ключ только в том случае, если он существует
Я нахожусь в базе данных MySQL.
Я делаю это, но это не работает.
ALTER TABLE `object` DROP FOREIGN KEY IF EXISTS `object_ibfk_1`;
Я пытался поставить этот IF EXISTS везде, где мог. Как проверить, существует ли внешний ключ перед его удалением?
Ответы
Ответ 1
Если вы хотите удалить внешний ключ, если он существует, и не хотите использовать процедуры, вы можете сделать это таким образом (для MySQL):
set @var=if((SELECT true FROM information_schema.TABLE_CONSTRAINTS WHERE
CONSTRAINT_SCHEMA = DATABASE() AND
TABLE_NAME = 'table_name' AND
CONSTRAINT_NAME = 'fk_name' AND
CONSTRAINT_TYPE = 'FOREIGN KEY') = true,'ALTER TABLE table_name
drop foreign key fk_name','select 1');
prepare stmt from @var;
execute stmt;
deallocate prepare stmt;
Если есть внешний ключ, мы помещаем оператор alter table в переменную, и если мы не добавляем фиктивный оператор. И затем мы его выполним.
Ответ 2
Для большей повторной юзабилити вы действительно захотите использовать хранимую процедуру. Запустите этот код один раз на требуемой БД:
DROP PROCEDURE IF EXISTS PROC_DROP_FOREIGN_KEY;
DELIMITER $$
CREATE PROCEDURE PROC_DROP_FOREIGN_KEY(IN tableName VARCHAR(64), IN constraintName VARCHAR(64))
BEGIN
IF EXISTS(
SELECT * FROM information_schema.table_constraints
WHERE
table_schema = DATABASE() AND
table_name = tableName AND
constraint_name = constraintName AND
constraint_type = 'FOREIGN KEY')
THEN
SET @query = CONCAT('ALTER TABLE ', tableName, ' DROP FOREIGN KEY ', constraintName, ';');
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
END$$
DELIMITER ;
После этого вы всегда можете заменить это:
ALTER TABLE `object` DROP FOREIGN KEY IF EXISTS `object_ibfk_1`;
с этим:
CALL PROC_DROP_FOREIGN_KEY('object', 'object_ibfk_1');
Затем ваш script должен гладко работать независимо от того, существует ли object_ibfk_1
или нет.
Много кредитов из-за: http://simpcode.blogspot.com.ng/2015/03/mysql-drop-foreign-key-if-exists.html
Ответ 3
IF EXISTS(
SELECT *
FROM INFORMATION_SCHEMA.STATISTICS
WHERE INDEX_SCHEMA = DATABASE()
AND TABLE_NAME='myTable'
AND INDEX_NAME = 'myIndex')
THEN
ALTER TABLE `myTable` DROP FOREIGN KEY `myForeignKey`;
ALTER TABLE `myTable` DROP INDEX `myIndex` ;
END IF;
При создании ограничения внешнего ключа mysql автоматически создаст индекс в столбце с ссылкой. В приведенном выше примере показано, как проверить индекс в INFORMATION_SCHEMA, но есть гораздо больше информации для вас в информационной схеме. Ваше имя индекса указывает на то, что оно было создано для FK, поэтому вам придется сначала отказаться от FK, а затем отбросить индекс. Если вы снова создадите внешний ключ, mysql снова создаст индекс. Он нуждается в индексе для обеспечения ссылочной целостности без необходимости выполнять сканирование таблицы.
Если вы планировали создать новый индекс, содержащий один и тот же столбец, сначала нужно создать этот индекс (с этим столбцом, который будет использоваться как FK, первым в списке столбцов указанный для индекса). Теперь вы можете добавить свой FK обратно, и mysql будет рад использовать новый индекс, не создавая другого.
Изменить: быстро просмотреть индексы просто выполнить ПОКАЗАТЬ ИНДЕКСЫ из myTable;
Ответ 4
Какую базу данных вы используете?
Если SQL Server
if exists (select 1 from sys.objects where object_id = OBJECT_ID(N'[FKName]') AND
parent_object_id = OBJECT_ID('TableName'))
alter table TableName drop constraint FKName
Ответ 5
Аналогичное обсуждение:
Как сбросить ограничение внешнего ключа, только если оно существует на сервере sql?
IF (OBJECT_ID('FK_ConstraintName', 'F') IS NOT NULL)
очень полезен и еще не упоминается здесь.