2012-12-13 18 views
8

Yabancı bir anahtar bir ad olmadan oluşturulduysa, MySql bunu varsayılan olarak verir. Örneğin, 'Test' tablosu için yabancı anahtar 'test_ibfk_1' olarak adlandırılacaktır. Bu ismi kullanarak yerel anahtarı yerel olarak bıraktığımda, bir çekicilik gibi çalışır, ancak geliştirme sunucusunda hata oluşur: 152.MySql'de adlandırılmamış Yabancı Anahtarını Gizle

Bu adın büyük/küçük harfe duyarlı olduğunu biliyorum, ancak küçük veya büyük harf sonucu aynıdır .

Soruma göre: Kısıtlamaları değiştirmek için varsayılan adı kullanmak güvenli midir (en azından MySql'de)?

Şimdiden teşekkürler!

cevap

14

Yabancı anahtarın adını bilmeniz gerekir. İsimsiz olarak oluşturulmuşsa, isim otomatik olarak üretilecektir. Yabancı anahtar hakkında bilgi almalısınız.

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; 

... ve yabancı anahtar bırakmak için ALTER TABLE <table_name> DROP INDEX <fk_name>; kullanmak - bu sorguları

kullanın bir yabancı anahtar adları alır.

+0

olmayan yöneticiler için yukarıdaki sorgu uygulanabilir mi: En genel çözüm beş değişkenlerle özelleştirebileceğiniz bu script? Genel bilgi bilmek çok iyi! Teşekkürler! –

+5

Sadece bu tür bir sorgu için fk_name'inizi almak için bu dayanıklılık trekinden geçmek zorunda kalmak utanç verici. 'ALTER tablo tablosu_adı' 'col_name' 'DROP CONSTRAINT ON (isim ne olursa olsun). Afterall, sadece belli bir anahtar üzerinde böyle bir kısıtlama olabilir. Herkes doğru mu? –

+1

@IfediOkonkwo, Tamamen katılıyorum. Birden çok ortamdaki veritabanında şema değişikliklerini yönetmek için Liquibase gibi bir şey kullanıyorsanız ve çalıştıkları her veritabanında aynı FK kısıtlama adını üretme garantisinin olmaması sorun yaratır. Bu, gelecekteki değişikliklerde bu kısıtlama adına güvenemeyeceğiniz anlamına gelir. Belli ki, başlangıçtan itibaren sabit bir adla kısıtlamaları adlandırabilirsiniz. –

3

Bir concatenate sorgusu oluşturma ve otomatik yürütme olmadan kaldırmak için ada bilebilir:

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; 

I yabancı anahtarın ismini öğrenmek gerekmez bu şekilde, sadece tablo_adı gereken size Yabancı anahtarı, veritabanı adını ve referans tablosunu kaldırmak istiyorum.

0

Acele okuyucu, bu cevaptan uzak durmuyor, sadece uzun olduğu için. Başka bir çözüm bulamazsınız, söz veriyorum

Kabul edilen cevap anahtarı düşürmez, sadece adını bulur. Anahtarı bilinmeyen bir adla gerçekten düşürmek için hazırlanmış ifadeleri kullanmanız gerekir.

-- 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; 
İlgili konular