I am using mysql as DB for my Laravel app.
In one table I have 5 fields that are foregin keys, those FK's points to 5 other tables primary keys.
Right now I have only marked them as FK, but do I need to put a index on every FK as well? Or does a FK count as a index?
Thanks in advance,
In mysql when making a FK it automatically indexes that column(s).
MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist. This index might be silently dropped later, if you create another index that can be used to enforce the foreign key constraint. index_name, if given, is used as described previously.
You can read more here at dev.mysql
Related
While designing the database for a laravel software using MYSQL, is assigning foreign keys relevant or does Laravel take care of that "Software side".
In the migration we have something like
Table Example:
$table->unsignedBigInteger('user_id');
should i modify the example table in phpmyadmin and make user_id a foreign key? is there a better way or is this not relevant or necessary?
You should define foreign key constraints in your migration. When using code base you should make all the changes using migrations.
Additionally by defining foreign key you actually build a relation between 2 tables otherwise this relation will be at code level. When relation is built database will restrict to have only values which actually exists in main table. Using foreign key you can also do cascading (on update and delete) at db level.
Reference what are the advantages of defining a foreign key
Why should I use foreign keys in database?
if use Laravel 7 ,you can use this short that is a column name user_id foreign to ID user in the table users :
$table->foreignId('user_id')->nullable()->constrained()->onDelete('cascade');
Why Does Laravel automatically add an “INDEX” for this condition?
$table->foreignId('user_id')->nullable()
->constrained('users','id')
->onDelete('no action')
->onUpdate('no action');
From https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html
MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist. This index might be silently dropped later if you create another index that can be used to enforce the foreign key constraint. index_name, if given, is used as described previously.
Laravel only adds a foreign key constraint and doesn't add index implicitly. But some databases such as MySQL automatically index foreign key columns.
When you define a foreign key constraint in your database table, an index will not be created automatically on the foreign key columns , as in the PRIMARY KEY constraint situation in which a clustered index will be created automatically when defining it. It is highly recommended to create an index on the foreign key columns, to enhance the performance of the joins between the primary and foreign keys, and also reduce the cost of maintaining the relationship between the child and parent tables. Before adding any new indexes, it is better to test on a development environment and monitor the overall performance after the implementation, to make sure that the added indexes improve performance and do not negatively impact the system performance.
Can I replace a table in DB through phpmyadmin. Table has two foreign keys and I can truncate it by disabling foreign key checks (or delete it completely), however when I try to reupload it, if I don't enable foreign key checks it doesn't connect to the tables it should (I can't click on foreign ID, usually it takes me to the related table). If I do enable foreign key checks I get an error
#1452 - Cannot add or update a child row: a foreign key constraint fails
Is there a way to somehow replace a table with the same table from the past by keeping the relations alive?
i think the table contains data ... try clearing the table before dropping it.
Actually "you don't need to disable foreign key checks" if you want to delete from (or truncate) only the table(s) where child records are stored. You should be able to delete all and re-insert them later. Please try it this way.
You need to disable the foreign key checks if you want to truncate the tables with primary keys without deleting the child records. (This is not reasonable though.)
The following steps in order should work fine without disabling any constraint. If you don't follow the order, it will fail. You can skip the steps 2 and 3 and use 1 and 4 only.
Delete all child records with foreign key pointing to a primary key.
Delete all master records with primary key.
Re-insert all master records with primary key.
Re-insert all child records with foreign key pointing to a primary key.
Anyway, the error you get sounds like when you try to insert the old data, the matching record is missing in the master table where the foreign key points to.
You can check:
Whether the data in the master tables (the tables with primary key where foreign keys point to) are also deleted or truncated. If so, you need to bring them back before the child records.
Whether the data in the master tables are not the same anymore and the consistency is lost with the old data. (If you are working on a production database, the data might be changing). If so, you need you need to bring the missing records back to the master table.
When i need to set a field as the foreign key in a table,in PHPMyAdmin. I am not getting it set right.
There is a Parent table called 'user' which has a primary key called 'uid'.I am using the 'uid' in the child table called 'student_register' as foreign key. But while setting it as foreign key constraint through the relation view link in phpmyadmin . i am not able to see the 'user' table in the drop down list to select it and set the 'uid' as foreign key .. I have sent the screen shot to get a clear picture.
the screenshot for the phpmyadmin child table 'student_register'
From the MYSQL User Guide:
If you are facing this issue than you need to follow these basic steps:
Database storage engine must be InnoDB.
Your relational tables must be InnoDB.
Use UNIQUE reference key.
Reference Key can not be NULL.
Datatype of the both columns must be same.
References:
Create Table Foreign Keys in MYSQL
Creating Foreign Key Relationships
You should add index to the column uid in table user in order to appear in the drop down list
Take the structure of table user, then click the last option of the Action - Add index for the column uid.
I have a table 'release_group' and another table 'release', like so:
release_group
------------------------
release_group_id (PRIMARY KEY)
name
main_release_id (FOREIGN KEY)
release
------------------------
release_id (PRIMARY KEY)
release_group_id (FOREIGN KEY)
name
If i create a release row, the release_group_id is not available, simply because it hasn't been created yet. But i can't create a release_group row without the main_release_id. So it's kind of a no way situation.
EDIT:
The main_release_id in release_group is to say that the release is the main from the group, the one i will use a reference.
What is the professional way of handling this case?
1.
Remove the foreign key index main_release_id in table release_group and give an attribute ALLOW NULL. Create the release_group row so i can applied it's id in the release row.
2.
Keep the 'main_release_id' foreign key index in table 'release_group' and assign it a temporary integer value of 0. Create the release row and update the foreign key in the release_group accordingly? Keep in mind that if this is the way to go, i could end up inadvertently having foreign keys with value 0, which i don't know if this ethic in a database?
What is the professional way of handling this case?
Thanks
Seeing how a release cannot belong to more than one group, you could remove the complication by:
Dropping the main_release_id field altogether
Add a release_main field to the release table; it would be NULL (not main) or 1 (main).
Add a UNIQUE constraint on (release_group_id, release_main) to make sure there can only be one main release.
Update
If a release can belong to multiple groups, you would need to create a many-to-many table and move the foreign key in both tables into it:
(release_group_id [FK], release_id [FK], is_main)
The primary key would span the first two fields. Ensuring that there can only be one main release requires a spanning unique key over the first and last field.
Old answer
Assuming main_release_id is a nullable field, what I would suggest is the following:
Insert the release_group with main_release_id being null; get last inserted id.
Insert the release entry, passing the id of the previous step; get last inserted id.
Update the release_group table entry, setting the value of main_release_id to the value you got from the previous step.
Commit transaction
Alternatively, you could use sequences so that you know the id before inserting the entries. See an example of this in the manual under LAST_INSERT_ID().
Looks like you are trying to create a many to many relationship. To do this properly, remove the foreign keys from both the release_group and release tables. Add a new table (release_to_release_group) that contains the release_id foreign key and the release foreign key.
Edit: There is no need for cyclic foreign keys here. Remove the main_release_id foreign_key from release_group and add a is_main_release flag to the release table.
It's not usual practice to have the tables reference each other like that. Usually you would have the Parent table (release_group) as a foreign key reference in the child table (release), but not have the release_id as a foreign key in the release_group table.
Maybe add a boolean flag to the release table to indicate it is the Main release and do away with the main_release_id in release_group.