If you are adding foreign keys, the referenced columns must match type definition exactly, and the field you're applying the index to must have valid data in it i.e. no values exist in the column you are creating a key on that does not exist in the foreign table.
If you have existing data, you'll need to do one of two things:
- Create and seed the foreign table with the existing index data first then create the migration to add the foreign keys
- Disable foreign key checks -
DB::statement('SET FOREIGN_KEY_CHECKS=0'); before your migration, DB::statement('SET FOREIGN_KEY_CHECKS=1'); after it.
The first option is (usually) the preferable one; it ensures integrity of your foreign key constraints. The second option will allow you to run the (invalid) migrations, but may lead to issues down the track when updating rows that contain invalid key data.
Generally speaking, the foreign key will be an integer referencing a record in another table that has more information such as a text description or key. If you're using a string (which is a less efficient index than what an unsigned integer would be), I would consider the possibility of tackling option 1.
Before the migration runs:
- Select all the unique values to be indexed
- Insert them into the foreign table
- Track the
id of the inserted values
- Update the relating table's data to match the new
id values
- Update the relating table's structure to be a nullable, unsigned integer
- Apply the foreign key index to the relating table
You can have multiple Schema::table() calls inside your up and downmigration methods, so you can conceivable run all of the above within a single migration.
How the foreign data was created will determine the best way forward here.