18

如果创建的外键没有名字,MySql 会给它一个默认值。例如,对于表“Test”,外键将命名为“test_ibfk_1”。当我使用此名称在本地删除外键时,它就像一个魅力,但在开发服务器上它失败并显示 errno: 152。

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

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

提前致谢!

4

4 回答 4

21

您需要知道外键的名称。如果创建时没有名称,则会自动生成名称。您应该获得有关外键的信息。

使用这些查询之一来获取外键名称 -

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>;删除外键。

于 2012-12-13T10:03:10.180 回答
7

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

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

-- 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;
于 2017-10-03T09:49:13.607 回答
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,数据库名称和引用表。

于 2016-06-30T15:15:37.547 回答
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;

我希望这对某人有用。

于 2020-10-20T10:32:44.980 回答