仅在外键存在时删除外键

时间:2013-06-18 05:56:51

标签: mysql sql foreign-keys

我在MySQL数据库上。

我这样做,但它不起作用。

ALTER TABLE `object` DROP FOREIGN KEY IF EXISTS `object_ibfk_1`;

我试图把这个IF EXISTS放在任何地方。如何在放弃之前检查外键是否存在?

7 个答案:

答案 0 :(得分:22)

如果要删除外键(不想使用过程),可以这样做(对于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语句放在变量中,如果没有,我们放置一个伪语句。然后我们执行它。

答案 1 :(得分:12)

为了获得更好的可重用性,您确实希望使用存储过程。在您想要的数据库上运行此代码一次:

   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');

无论object_ibfk_1是否确实存在,您的脚本都应该顺利运行。

很多功劳归于:http://simpcode.blogspot.com.ng/2015/03/mysql-drop-foreign-key-if-exists.html

答案 2 :(得分:10)

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中检查索引,但是有更多信息可供您查看information schema。您的索引名称似乎表明它是为FK创建的,因此您必须先删除FK,然后删除索引。如果再次创建外键,mysql将再次创建索引。它需要一个索引来强制引用完整性而无需进行表扫描。

如果您打算创建一个包含相同列的新索引,则必须首先创建该索引(使用此列,将用作FK的列,是列列表中的第一个为索引指定)。现在你可以添加你的FK了,mysql很乐意使用新索引而不创建另一个索引。

编辑:快速查看索引只需执行SHOW INDEXES FROM myTable;

答案 3 :(得分:1)

您正在使用哪个数据库?

如果是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

答案 4 :(得分:0)

在当前版本的Mariadb 10.1.26(新的Mysql)中,您的查询有效:

键: MUL

ALTER TABLE `object` DROP FOREIGN KEY IF EXISTS `object_ibfk_1`;
DESC `object`;

键: <NULL>

答案 5 :(得分:0)

这是DROP FOREIGN KEY IF EXISTS的一种解决方法,在v10.1.4之前的MySQL和MariaDB版本中缺少。您还可以将其用于所需的其他所有语句,具体取决于FOREIGN KEY的存在(例如,对于SELECT "info: foreign key exists.",如下例所示)。

-- DROP FOREIGN KEY IF EXISTS
SELECT
    COUNT(*)
INTO
    @FOREIGN_KEY_my_foreign_key_ON_TABLE_my_table_EXISTS
FROM
    `information_schema`.`table_constraints`
WHERE
    `table_schema` = 'my_database'
    AND `table_name` = 'my_table'
    AND `constraint_name` = 'my_foreign_key'
    AND `constraint_type` = 'FOREIGN KEY'
;
-- SELECT @FOREIGN_KEY_my_foreign_key_ON_TABLE_my_table_EXISTS;
SET @statement := IF(
    @FOREIGN_KEY_my_foreign_key_ON_TABLE_my_table_EXISTS > 0,
    -- 'SELECT "info: foreign key exists."',
    'ALTER TABLE my_table DROP FOREIGN KEY my_foreign_key',
    'SELECT "info: foreign key does not exist."'
);
PREPARE statement FROM @statement;
EXECUTE statement;

答案 6 :(得分:-3)

类似的讨论: How do I drop a foreign key constraint only if it exists in sql server?

IF (OBJECT_ID('FK_ConstraintName', 'F') IS NOT NULL)

非常实用,此处尚未提及。