2009-08-24 34 views
14

Trong mySQL 5, có cách nào để loại bỏ tất cả các ràng buộc khóa ngoài trên một bảng với một câu lệnh SQL mà không đề cập đến chúng theo tên không?Có thể thả tất cả các ràng buộc khoá ngoại trên bàn cùng lúc trong mySQL 5 không?

Tôi đang viết tập lệnh cập nhật DB và rất tiếc một số trang web có các ràng buộc được tạo bằng tên "sai". Tôi đang cố gắng tránh đi vào và nhận được các tên ràng buộc thực tế từ DB và chèn chúng trở lại vào các câu lệnh SQL.

Trả lời

6

Bạn chắc chắn có thể chọn * bảng vào bảng tạm thời, thả và tạo lại bảng, sau đó sao chép lại.

+1

Đối với tôi nhận được lỗi như 'Không thể xóa hoặc cập nhật hàng mẹ: một ràng buộc khoá ngoại thất bại'. Tôi đã cố tạo từng hàng rồi chỉ cho một hàng bị lỗi, số khác bị xóa. – Pramod

+1

"Chắc chắn" hầu như không. Trong các bảng thế giới thực thường là quá lớn cho điều này là khả thi. Không có cách nào để thao tác các chỉ mục mà không cần tạo lại toàn bộ bảng? (Có: ​​xem giải pháp tuyệt vời của Dandalf!) –

6

Trong tập lệnh, bạn luôn có thể thêm SET FOREIGN_KEY_CHECKS = 0 nếu bạn chỉ muốn vượt qua các ràng buộc.

hạn chế Ngoài ra, tôi đã luôn luôn bị xóa trên một cơ sở cho mỗi hạn chế sử dụng:

ALTER TABLE <table_name> DROP FOREIGN KEY <key_name>; 

Tôi không nghĩ rằng bạn có thể làm tất cả chúng cùng một lúc và tôi không thể tìm thấy bất kỳ ví dụ cho thấy bạn có thể.

6

Bạn có thể sử dụng kịch bản này đơn giản bash:

Run:

sh deleteForeignKeys.sh 

và deleteForeignKeys.sh là

#!/bin/bash 

dbname="databasename" 
table="tablename" 

mysqlconn="mysql -u username -ppassword -h host" 

tableschema=$($mysqlconn -N -e "SHOW CREATE TABLE $dbname.$table") 

#Foreign Keys 
fks=$(echo $tableschema | grep -oP '(?<=CONSTRAINT `).*?(?=` FOREIGN KEY)') 

for fk in $fks; 
do 
    # DROP FOREIGN KEY 
    $mysqlconn -e "ALTER TABLE $dbname.$table DROP FOREIGN KEY $fk"; 
done 
7

Dưới đây là một lựa chọn mà tạo ra hoàn toàn thả và tạo báo cáo cho tất cả các mối quan hệ trên một cái bàn. Không tự động trong bất kỳ cách nào, nhưng dễ dàng đủ để sao chép/dán từ ..

SELECT `DROP`,`CREATE` FROM (
SELECT 
CONCAT("ALTER TABLE `", `K`.`TABLE_NAME`, "` DROP FOREIGN KEY `", `K`.`CONSTRAINT_NAME`, "`;") "DROP", 
CONCAT("ALTER TABLE `", 
`K`.`TABLE_NAME`, 
"` ADD CONSTRAINT ", 
"`fk_", 
`K`.`TABLE_NAME`, 
"_", 
`K`.`REFERENCED_TABLE_NAME`, 
"1", 
"` FOREIGN KEY (`", 
`K`.`COLUMN_NAME`, 
"`) REFERENCES ", 
"`", 
`K`.`REFERENCED_TABLE_SCHEMA`, 
"`.`", 
`K`.`REFERENCED_TABLE_NAME`, 
"` (`", 
`K`.`REFERENCED_COLUMN_NAME`, 
"`) ON DELETE ", 
`C`.`DELETE_RULE`, 
" ON UPDATE ", 
`C`.`UPDATE_RULE`, 
";") "CREATE" 
FROM `information_schema`.`KEY_COLUMN_USAGE` `K` 
LEFT JOIN `information_schema`.`REFERENTIAL_CONSTRAINTS` `C` USING (`CONSTRAINT_NAME`) 
WHERE `K`.`REFERENCED_TABLE_SCHEMA` = "your_db" 
AND `K`.`REFERENCED_TABLE_NAME` = "your_table") AS DropCreateConstraints 

tôi sử dụng nó để thả tất cả các mối quan hệ, thay đổi các kiểu dữ liệu trên các phím và sau đó khôi phục lại mối quan hệ với những cái tên quan trọng nước ngoài á la MySQL Workbench. Có thể hữu ích cho ai đó ..

11

Tôi có một giải pháp tương tự như câu trả lời của Bing, nhưng phải mất thêm một bước để tự động và có thể tái sử dụng trong quy trình.

DROP PROCEDURE IF EXISTS dropForeignKeysFromTable; 

delimiter /// 
create procedure dropForeignKeysFromTable(IN param_table_schema varchar(255), IN param_table_name varchar(255)) 
begin 
    declare done int default FALSE; 
    declare dropCommand varchar(255); 
    declare dropCur cursor for 
     select concat('alter table ',table_schema,'.',table_name,' DROP FOREIGN KEY ',constraint_name, ';') 
     from information_schema.table_constraints 
     where constraint_type='FOREIGN KEY' 
      and table_name = param_table_name 
      and table_schema = param_table_schema; 

    declare continue handler for not found set done = true; 

    open dropCur; 

    read_loop: loop 
     fetch dropCur into dropCommand; 
     if done then 
      leave read_loop; 
     end if; 

     set @sdropCommand = dropCommand; 

     prepare dropClientUpdateKeyStmt from @sdropCommand; 

     execute dropClientUpdateKeyStmt; 

     deallocate prepare dropClientUpdateKeyStmt; 
    end loop; 

    close dropCur; 
end/// 

delimiter ; 

Vì một câu lệnh chuẩn bị chỉ có thể xử lý một câu lệnh tại một thời điểm, thủ tục lặp qua các khóa ngoài bằng cách sử dụng con trỏ và thực hiện từng lần một.

Để sử dụng các thủ tục trên một trong những bảng của bạn chỉ cần sử dụng những điều sau đây, thay thế table_schema và tên_bảng với các giá trị của bạn:

call dropForeignKeysFromTable('table_schema', 'table_name'); 
+1

Quy trình tuyệt vời! Hoạt động tuyệt vời! – Livewire

+0

Đây là những gì tôi đang tìm kiếm. Tuyệt vời làm việc Dandalf! –

+0

Hoạt động như một sự quyến rũ. Cảm ơn !! –

Các vấn đề liên quan