Reputation: 5417
I'm stuck with this infamous error and can't figure out what went wrong. I'm trying to establish relationship between two tables orders
and payments
, whose migrations are defined as:
class CreateOrdersTable extends Migration
{
public function up()
{
Schema::create('orders', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->integer('customer_id')->unsigned();
$table->integer('partner_id')->unsigned();
$table->string('status', 20)->default(Order::getDefaultStatus());
$table->string('paid', 20)->default('no');
$table->decimal('visitation_charges', 20, 2)->default(0);
$table->decimal('taxes', 20, 2)->default(0);
$table->decimal('charges', 20, 2)->default(0);
$table->decimal('discount', 20, 2)->default(0);
$table->decimal('total', 20, 2)->default(0);
$table->foreign('customer_id')->references('id')
->on('customers')->onDelete('cascade')
->onUpdate('cascade');
$table->foreign('partner_id')->references('id')
->on('partners')->onDelete('cascade')
->onUpdate('cascade');
});
}
public function down()
{
Schema::dropIfExists('orders');
}
}
class CreatePaymentsTable extends Migration
{
public function up()
{
Schema::create('payments', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->integer('order_id')->unsigned();
$table->string('gateway', 100);
$table->string('transaction_id', 100);
$table->decimal('amount', 20, 2);
$table->string('status', 20)->default(Payment::getDefaultStatus());
$table->string('comments', 2000)->nullable();
$table->foreign('order_id')->references('id')
->on('orders')->onDelete('set null')
->onUpdate('cascade');
});
}
public function down()
{
Schema::dropIfExists('payments');
}
}
The error I get is:
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `payments` add constraint `payments_order_id_foreign` foreign key (`order_id`) references `orders` (`id`) on delete set null on update cascade)
I've also verified that the table engines, column types, character set, etc., are the same (following are the outputs of show create
):
| orders | CREATE TABLE `orders` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`customer_id` int(10) unsigned NOT NULL,
`partner_id` int(10) unsigned NOT NULL,
`status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'created',
`paid` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'no',
`visitation_charges` decimal(20,2) NOT NULL DEFAULT '0.00',
`taxes` decimal(20,2) NOT NULL DEFAULT '0.00',
`charges` decimal(20,2) NOT NULL DEFAULT '0.00',
`discount` decimal(20,2) NOT NULL DEFAULT '0.00',
`total` decimal(20,2) NOT NULL DEFAULT '0.00',
PRIMARY KEY (`id`),
KEY `orders_customer_id_foreign` (`customer_id`),
KEY `orders_partner_id_foreign` (`partner_id`),
CONSTRAINT `orders_customer_id_foreign` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `orders_partner_id_foreign` FOREIGN KEY (`partner_id`) REFERENCES `partners` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
| payments | CREATE TABLE `payments` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`order_id` int(10) unsigned NOT NULL,
`gateway` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`transaction_id` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`amount` decimal(20,2) NOT NULL,
`status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'pending',
`comments` varchar(2000) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
Not sure where I'm going wrong. :/
Upvotes: 1
Views: 1381
Reputation: 745
Add nullable() on order_id column. Like below. Your error will be gone.
class CreatePaymentsTable extends Migration
{
public function up()
{
Schema::create('payments', function (Blueprint $table) {
// your others columns
$table->integer('order_id')->unsigned()->nullable();
}
}
Upvotes: 2
Reputation: 176
it should better you build another migration for foreign key:
php artisan make:migration add_foreign_key_to_payment_table --table=payments
so add payments foreign key to this migration, then run php artisan migrate
if the error still exists you must drop manually orders and payments table and remove them from migration table then add those again.
I hope this will help you. Good day! :)
Upvotes: 1
Reputation: 562280
You can't make a foreign key ON DELETE SET NULL
for columns declared as NOT NULL
.
The column can't be NULL.
The foreign key works if you do either of the following:
Omit the ON DELETE SET NULL
:
alter table `payments` add constraint `payments_order_id_foreign`
foreign key (`order_id`) references `orders` (`id`) on update cascade;
Modify the column to allow NULL:
alter table payments modify order_id int(10) unsigned null;
Upvotes: 4