如果创建的外键没有名字,MySql 会给它一个默认值。例如,对于表“Test”,外键将命名为“test_ibfk_1”。当我使用此名称在本地删除外键时,它就像一个魅力,但在开发服务器上它失败并显示 errno: 152。
我知道这个名称区分大小写,但无论是小写还是大写,结果都是一样的。
我的问题:依靠默认名称来操纵约束是否安全(至少在 MySql 中)?
提前致谢!
如果创建的外键没有名字,MySql 会给它一个默认值。例如,对于表“Test”,外键将命名为“test_ibfk_1”。当我使用此名称在本地删除外键时,它就像一个魅力,但在开发服务器上它失败并显示 errno: 152。
我知道这个名称区分大小写,但无论是小写还是大写,结果都是一样的。
我的问题:依靠默认名称来操纵约束是否安全(至少在 MySql 中)?
提前致谢!
您需要知道外键的名称。如果创建时没有名称,则会自动生成名称。您应该获得有关外键的信息。
使用这些查询之一来获取外键名称 -
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>;
删除外键。
匆忙的读者,不要离开这个答案,只是因为它很长。你不会找到另一个解决方案,我保证:)
接受的答案不会删除密钥,它只会找到它的名称。要真正删除名称未知的密钥,您需要使用准备好的语句。最通用的解决方案是这个脚本,您可以使用五个变量进行自定义:
-- 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;
您可以在不知道名称的情况下删除,创建连接查询并自动执行:
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,数据库名称和引用表。
如果有人对如何从表中删除所有外键感兴趣,我们在更新存储过程中使用此代码(该示例应用于我们内部数据库中的表 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;
我希望这对某人有用。