Laravel Eloquent truncate - Foreign key constraint - php

I am having some issues with deleting data using Laravel 5. I seem to be stuck on a 'foreign key constraint', while I don't see why.
In my current database model I have a datapoints table, which has a foreign key to the sensors table (datapoints.sensors_id -> sensor.id).
The code I am trying:
Route::get('/truncateData', function() {
DB::table('datapoints')->truncate();
DB::table('sensors')->truncate();
return 'Done...';
});
The result:
SQLSTATE[42000]: Syntax error or access violation: 1701 Cannot
truncate a table referenced in a foreign key constraint
(alerting.datapoints, CONSTRAINT datapoints_sensor_id_foreign
FOREIGN KEY (sensor_id) REFERENCES alerting.sensors (id))
(SQL: truncate sensors)
I would understand this constraint if the order would be inverse (first deleting sensors), but when datapoints is empty, there should be no problem deleting sensors? I have also tried:
DB::table('datapoints')->delete();
DB::table('sensors')->delete();
return 'Done...';
Lastly I also tried adding explicitly 'DB::commit()' between the delete statements, but all return the same result.
Is this normal behaviour? Am I missing something?

No, this is the way your database works. You can't truncate table that is referenced by some other table. You may do something like
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
DB::table('datapoints')->truncate();
DB::table('sensors')->truncate();
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
to disable foreign key checks, truncate tables and enable it again.

If you prefer to use Eloquent objects, Maksym's answer the "Eloquent" way
use Illuminate\Support\Facades\Schema;
use App\Models\Datapoint;
use App\Models\Sensor;
Schema::disableForeignKeyConstraints();
Datapoint::truncate();
Sensor::truncate();
Schema::enableForeignKeyConstraints();

In Laravel 7 and 8, for compatibility across 4 databases (MySql, Postgres, SQLite and SqlServer) and no Eloquent, you can use:
Schema::disableForeignKeyConstraints();
DB::table('datapoints')->truncate();
DB::table('sensors')->truncate();
Schema::enableForeignKeyConstraints();

Related

Laravel Migration create foreign key using foreignIdFor with specific data type?

So I've been trying to write a migration that creates a data table question_display_formats using tiny increments as you see below.
And then, adding new Foreign Key column to existing questions table, trying to use the foreignIdFor method as a shortcut that'd look nice
public function up()
{
Schema::create('question_display_formats', function (Blueprint $table) {
$table->tinyIncrements('id');
$table->string('format');
});
Schema::table('questions', function (Blueprint $table) {
$table->foreignIdFor(QuestionDisplayFormat::class)
->nullable(true)
->after('question_type_id')
->constrained();
});
}
Turns out, this errors out with
General error: 1215 Cannot add foreign key constraint
Which turns out because the foreignIdFor users a different data type (confirmed by manually matching them and running the erroring out SQL alter table statement).
I googled, read and tried to adjust by doing:
$table->mediumIncrements('question_display_format_id'); before the foreignIdFor line, which leads to error
SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name
'question_display_format_id' (SQL: alter table questions add
question_display_format_id mediumint un signed not null
auto_increment primary key, add question_display_format_id bigint
unsigned null after question_type_id)
Is there a way to use foreignIdFor with the matching column size? or am I supposed to fall back on the classic way of first creating the column explicitly, then doing like $table->foreign('question_display_format_id')->references('id')->on('question_display_formats'); which I don't like because its very verbose and doesn't look good?
On the other hand, this is a one time used script.. lol would've been faster to just do it the old way! but I am curious to see how to do it right :)

(Laravel & SQL) Alternative method for setting foreign key cheks in seeders situation

To prevent "SQLSTATE[42000]: Syntax error or access violation: 1701 Cannot truncate a table referenced in a foreign key constraint.." when running DatabaseSeeder(.php) method run(), I set foreign key checks to 0, then call table seeders, and after that set foreign key checks again to 1. I feel like this isn't the best thing to do here, so I'd like to know what's the best syntax solution (if this isn't):
public function run()
{
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
$this->call(RolesTableSeeder::class);
$this->call(UsersTableSeeder::class);
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
}
The best solution is to delete the objects referenced in foreign key constraints first.

What is this second parameter in the foreign method in migration Laravel?

I'm working with Laravel in this new project but there's one piece of code that I don't know what it does.
$table->foreign('course_id', '54419_596eedbb6686e')->references('id')->on('courses');
The line above is one of my migration files, I know that I'm saying that the 'course_id' is a foreign key with relation to 'id' on courses table. But what I don't know is what is this second parameter ('54419_596eedbb6686e'), if I look in the method description it says that is a name, but a name for what? Am I supposed to create a number like this and put it in all my foreign keys? Is there a command to generate this number?
Anyway if anyone can help me to understand this piece of code it would be great.
Hope I was clear on the question.
The second parameter is the name for your foreign key.
By default the name of the foreign key for this $table->foreign('course_id')->references('id')->on('courses'); will be courses_course_id_foreign.
In this case $table->foreign('course_id', '54419_596eedbb6686e')->references('id')->on('courses'); your foreign key will be named as 54419_596eedbb6686e.
When you create a foreign key you are creating a constraint and that's what the second parameter of foreign() function is specifying: the constraint name.
If you are using mysql you can log in the shell(or whatever program you use to check the db out) and run SHOW CREATE TABLE table_name. that will output information about that table you specified. There you'll be able to see '54419_596eedbb6686e' as a constraint of your table. Something like this:
CONSTRAINT constraint_name FOREIGN KEY (column_id) REFERENCES table_name (id) ON DELETE CASCADE
You can find a little more information in the following links: MySQL FOREIGN KEY syntax
SQL FOREIGN KEY on CREATE TABLE
When you create migration let this in your migration for foreign key
$table->foreign('foreign_id')
->references('id')->on('main_table_name')
->onUpdate('CASCADE')
->onDelete('RESTRICT');

add 'on update' & 'on delete' foreign key constraints with laravel migrations

I am making my table like this...
Schema::create('matched_merchants', function (Blueprint $table)
{
$table->increments('id')->unsigned();
$table->integer('merchant_id')->unsigned();
$table->integer('offer_id')->unsigned();
$table->foreign('merchant_id')->references('id')->on('merchants')->onUpdate('cascade')->onDelete('restrict');
$table->foreign('offer_id')->references('id')->on('offers')->onUpdate('cascade')->onDelete('restrict');
});
Im adding 2 foreign keys both have onUpdate and onDelete constraints but only the update constraint gets added.
If i delete the onUpdate, it will correctly add the onDelete constraint.
I cannot add them separately because i get the error of duplicate key.
I could add them manually with a raw sql statement but if theres a right way to do it id rather do that.
For some reason, if you set the columns as nullable(), Laravel sets the foreign keys correctly.
That said, I can see that causing other problems, so I recommend doing the raw SQL statement.

How to drop foreign key using Laravel migrations?

I've tried to drop a an InnoDB table that holds a foreign key using Laravel Migrations but I found out that I need to drop the foreign first but what I've read on the doc and on articles doesn't work.
Here's the portion of the code creating the problem :
Schema::table('admin_admin_action', function(Blueprint $table) {
$table->dropForeign(['admin_action_id']);
$table->dropColumn('admin_action_id');
$table->dropForeign(['admin_id']);
$table->dropColumn('admin_id');
});
And here's the error code
Illuminate\Database\QueryException : SQLSTATE[42000]: Syntax error or access violation: 1091 Can't DROP 'admin_admin_action_admin_action_id_foreign'; check that column/key exists (SQL: alter table `admin_admin_action` drop foreign key `admin_admin_action_admin_action_id_foreign`)
This table is the result of a many to many association and here are the foreign keys
Schema::table('admin_admin_action', function($table) {
$table->unsignedInteger('admin_id');
$table->unsignedInteger('admin_action_id');
$table->foreign('admin_id')->references('id')->on('admin');
$table->foreign('admin_action_id')->references('id')->on('admin_actions');
});
I've also tried specifying the full foreign key name but it says that the key/column doesn't exist though it does exist in the database.
I'm doubting this is a migration's issue because the migration runs smoothly but that's not the case for the rollback.
Edit: The foreign keys are respectively named
admin_admin_action_admin_id_foreign
admin_admin_action_admin_action_id_foreign
Help!
I found the solution !
You're right ! It's a mis-conception issue I've created a "admin_admin_action" and an "admin_action_admin" tables. So I've been trying to the table that doesn't have the foreign keys but has the same position in the database. They're duplicated ! Thanks

Categories