2013-06-14 15 views
32

Tôi đang cố gắng phục hồi các lần di chuyển của mình.Sử dụng di chuyển để xóa bảng có khóa ngoài

tập tin di cư của tôi sử dụng phím nước ngoài như vậy

$table->foreign('user_one')->references('id')->on('users'); 
$table->foreign('user_two')->references('id')->on('users'); 

xuống của tôi() chức năng là như vậy

public function down() 
{ 
    Schema::drop('pm_convo'); 
    Schema::drop('pm_convo_replys'); 
} 

Khi tôi chạy lệnh di cư của tôi

php artisan migrate:refresh --seed --env=local 

Tôi nhận được lỗi sau đây

SQLSTATE[23000]: Integrity constraint violation: 1217 Cannot delete or update a parent row: a foreign key constraint fails (SQL: drop table `pm_convo`) 

Tôi không biết chắc phải làm gì để sửa lỗi này.

Edit:

Tôi đã thử: $table->dropForeign('pm_convo_user_one_foreign');

Nhưng im nhận lỗi với điều đó cũng

+0

Bạn có một bảng mà có một chìa khóa nước ngoài tham chiếu đến 'pm_convo'? –

+0

Có tôi làm .. Có một bảng gọi là pm_convo_replys có $ table-> foreign ('c_id_fk') -> references ('id') -> on ('pm_convo'); – BigJobbies

+0

Trong trường hợp đó, chuyển hai cuộc gọi thả xuống. –

Trả lời

46

pm_convo_replys có một khóa ngoại tham chiếu pm_convo, do đó bạn không thể xóa pm_convo đầu tiên mà không vi phạm ràng buộc khóa ngoại trong pm_convo_replys.

Để xóa cả hai bạn cần phải xóa pm_convo_replys trước tiên.

public function down() 
{ 
    Schema::drop('pm_convo_replys'); 
    Schema::drop('pm_convo'); 
} 
57

Tôi nghĩ rằng đây là một cách tốt hơn để làm điều đó:

public function down() 
{ 
    DB::statement('SET FOREIGN_KEY_CHECKS = 0'); 
    Schema::dropIfExists('tableName'); 
    DB::statement('SET FOREIGN_KEY_CHECKS = 1'); 
} 
+4

Đây là một cách dễ dàng hơn để làm điều này cho chắc chắn nếu bạn có rất nhiều phím nước ngoài để giải quyết nhưng điều này sẽ làm việc với tất cả các loại cơ sở dữ liệu? Ngoài ra nó sẽ không thể được trong quá trình phát triển nếu di chuyển của bạn không hoàn toàn đúng để vô tình để lại kiểm tra chìa khóa nước ngoài? Cá nhân tôi cảm thấy sạch hơn của nó chỉ để ra lệnh cho họ một cách chính xác – WebweaverD

+0

Thx, giải pháp này đã giải quyết vấn đề của tôi với một truncate trên hạt giống cơ sở dữ liệu của tôi. – ke20

+0

Tôi nghĩ rằng nó là không khôn ngoan để sử dụng 'dropIfExists' ở đây. Về nguyên tắc, tôi thấy nó là tốt hơn để viết di cư dựa vào trạng thái hiện tại của cơ sở dữ liệu là những gì bạn nghĩ nó là. Nếu trạng thái của cơ sở dữ liệu khác với những gì bạn mong đợi khi hàm 'down' chạy (nói bảng không tồn tại), thì rất có thể có điều gì đó không đúng với hàm' up' của bạn, và bạn thực sự cần sửa lỗi đầu tiên. –

3

thích làm theo cách này

Schema::dropIfExists('tableNameChild'); 
    Schema::drop('tableNameParents'); 
5

Tôi cũng phải đối mặt với loại vấn đề. Thứ tự tệp di chuyển là vấn đề chính ở đây. Cách tốt nhất là tạo từng tệp di chuyển. Các thực thể chính phải được tạo đầu tiên. Di chuyển phải được làm mới với mỗi lần tạo tệp di chuyển. (Với php artisan migrate:refresh)

Theo @abkrim và @ Eric

public function down() 
{ 
    Schema::disableForeignKeyConstraints(); 
    Schema::drop('tableName'); 
    Sch‌​ema::enableForeignKe‌​yConstraints(); 
} 
2

Tôi nghĩ rằng đây là cách tiếp cận đúng nhất:

public function down() 
{ 
    Schema::table('[table]', function (Blueprint $table) { 
     $table->dropForeign('[table]_[column]_foreign'); 
     $table->dropColumn('[column]'); 
    }); 
}