如果创建的外键没有名称,MySql将为其指定默认值。例如,对于表'Test',外键将命名为'test_ibfk_1'。当我通过使用此名称在本地删除外键时,它就像一个魅力,但在开发服务器上它失败了errno:152。
我知道这个名字区分大小写,但无论是大写还是大写,结果都是一样的。
我的问题:依靠默认名称来操纵约束是否安全(至少在MySql中)?
提前致谢!
答案 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;
我希望这对某人有用。