在MySql中删除未命名的外键

时间:2012-12-13 09:38:09

标签: mysql foreign-keys

如果创建的外键没有名称,MySql将为其指定默认值。例如,对于表'Test',外键将命名为'test_ibfk_1'。当我通过使用此名称在本地删除外键时,它就像一个魅力,但在开发服务器上它失败了errno:152。

我知道这个名字区分大小写,但无论是大写还是大写,结果都是一样的。

我的问题:依靠默认名称来操纵约束是否安全(至少在MySql中)?

提前致谢!

4 个答案:

答案 0 :(得分:17)

您需要知道外键的名称。如果它是在没有名称的情况下创建的,那么名称将自动生成。您应该获得有关外键的信息。

使用其中一个查询获取外键名称 -

SELECT
  constraint_name
FROM
  information_schema.REFERENTIAL_CONSTRAINTS
WHERE
  constraint_schema = <'db_name'> AND table_name = <'table_name'>;


SELECT *
FROM
  information_schema.KEY_COLUMN_USAGE
WHERE
  constraint_schema = <'db_name'> AND table_name = <'table_name'> AND   
  referenced_table_name IS NOT NULL;

...并使用ALTER TABLE <table_name> DROP INDEX <fk_name>;删除外键。

答案 1 :(得分:3)

您可以在不知道名称的情况下删除,创建连接查询并自动执行:

set @s:='';
select @s:=concat(@s, 'alter table ', 'your_table', ' drop foreign key ',CONSTRAINT_NAME, ';')
from information_schema.key_column_usage
where CONSTRAINT_SCHEMA = 'your_database'
  and TABLE_NAME ='your_table'
  and REFERENCED_TABLE_NAME = 'the_foreign_reference_table';
prepare stmt from @s;
execute stmt;

deallocate prepare stmt;

我那样你不需要知道外键的名称,只需要你要删除外键的table_name,数据库名称和引用表。

答案 2 :(得分:3)

匆匆的读者,不要放弃这个答案,因为它很长。你不会找到另一个解决方案,我保证:)

接受的答案不会丢弃密钥,它只会找到它的名字。要实际删除具有未知名称的密钥,您需要使用预准备语句。最通用的解决方案是这个脚本,您可以使用五个变量进行自定义:

-- YOU MUST SPECIFY THESE VARIABLES TO FULLY IDENTIFY A CONSTRAINT
SET @table_name = '...';
SET @column_name = '...';
SET @referenced_table_name = '...';
SET @referenced_column_name = '...';
-- make sure to limit queries to a single db schema
SET @db_name = '...'; 

-- find the name of the foreign key and store it in a var
SET @constraint_name = (
    SELECT constraint_name
    FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
    WHERE TABLE_NAME = @table_name
        AND COLUMN_NAME = @column_name
        AND CONSTRAINT_SCHEMA = @db_name
        AND referenced_table_name = @referenced_table_name
        AND referenced_column_name = @referenced_column_name);


-- prepare the drop statement in a string and run it
SET @s = concat('alter table ', @table_name, ' drop foreign key ', @constraint_name);

PREPARE stmt FROM @s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

答案 3 :(得分:0)

如果有人对如何从表中删除所有外键感兴趣,我们将在更新存储过程中使用此代码(该示例适用于内部数据库中的表db_Order):

DECLARE counter INT DEFAULT 1;
DECLARE foreignKeyDeleteStatement VARCHAR(200) DEFAULT '';

...

SET counter = (SELECT COUNT(1) FROM information_schema.TABLE_CONSTRAINTS
    WHERE CONSTRAINT_TYPE = 'FOREIGN KEY' AND table_schema=DATABASE() AND table_name='db_Order');
    SELECT 'Number of foreignKeys on table db_Order = ' + counter;

WHILE counter > 0 DO
                SELECT concat('ALTER TABLE ', TABLE_NAME, ' DROP FOREIGN KEY ', CONSTRAINT_NAME, ';') 
                FROM information_schema.key_column_usage 
                WHERE CONSTRAINT_SCHEMA = DATABASE()
                AND TABLE_NAME='db_order' 
                AND REFERENCED_TABLE_NAME IS NOT NULL
                LIMIT 1
                INTO foreignKeyDeleteStatement;
                
                SELECT foreignKeyDeleteStatement;
                
                SET @s = foreignKeyDeleteStatement;
        
                PREPARE stmt1 FROM @s;
                EXECUTE stmt1;
                DEALLOCATE PREPARE stmt1;
                
                SET counter = counter - 1;
END WHILE;

我希望这对某人有用。