I'm new to programming so please forgive my ignorance. I'm trying to get MySQL tables to update each other. For example: When I insert data into a Primary Key column in one table, it does not appear in it's Foreign Key column in another table.
Does anyone have any advice on this issue?
Thank you!
Additional Information: I used phpMyAdmin to create my tables and then added SQL code to create the Foreign Keys. Example of code is below.
ALTER TABLE CourseSchedule
ADD FOREIGN KEY (CourseId)
REFERENCES Course(CourseId)
I believe what we have here is a slight misunderstanding of the documentation.
For storage engines supporting foreign keys, MySQL rejects any INSERT
or UPDATE operation that attempts to create a foreign key value in a
child table if there is no a matching candidate key value in the
parent table.
When an UPDATE or DELETE operation affects a key value in the parent
table that has matching rows in the child table, the result depends on
the referential action specified using ON UPDATE and ON DELETE
subclauses of the FOREIGN KEY clause. MySQL supports five options
regarding the action to be taken, listed here
What your foreign key actually does is to make sure that you cannot insert values into your CourseSchedule table that do not correspond to an entry in the Courses table.
To give you an example, suppose you were to try to enter schedule a python course for every wednesday at 9:00 but you dont' actually have an entry for python in your Courses table. Then mysql will refuse to create that entry. Mysql cannot do the reverse. It doesn't know details about your python course. So it cannot automatically create a entry in the Courses table for you. Similarly, if oyu created an entr in the courses table. Mysql cannot automatically create a CourseSchedule for you because it doesn't know at what time it should be scheduled.
Related
I'm using symfony 4 and when I do links between tables there are indexes created. I do not understand how they work.
What is their purpose and why is it impossible to import data file into those files.
Is it possible to 'bypass' this mysql restriction and import data-files into mysql even if there is a constraint (without breaking the indexes)?
Thanks
MySQL is a relational database system. If there is a relationship between 2 tables, it is there for a reason. Think of your entities in Symfony. If one entity (a primary entity) has several related entities and those related entities can only exist if there is a primary entity, then the constraint must exist to prevent orphaned records.
For example:
Consider the relationship between companies and divisions. A company can have 0 or more divisions, but a division can only exist as a part of a company. In this case, a record in the division table would have a reference to a record in the company table. However, a record in a company table would have no direct reference in MySQL to any records in the division table.
To prevent a division from being created without a company, you cannot insert a row into the division table that does not reference a record in the company table.
To finally answer the question directly, you can only import data that does not reference the primary table by removing the foreign key constraint (this will not destroy the index). Keep in mind that this will likely result in records that are "orphaned" and do not fit the business model you are trying to create.
Rather than removing the foreign key constraint, you should first import the data to the referenced table (scoring?) and then update the data being imported to contain the correct ids to reference the primary table.
Based on the information in the image provided, each record in the file being imported should have a value for scoring_id that is equal to (presumably) the id field in the scoring table. If there is some other piece of data that can be used to link the 2 tables, use that and configure your entities appropriately.
Mysql FOREIGN KEY is used for data integrity. So what happens is you have a Foreign key which refers to column in another table .It's a way to link data relationships between tables
When Using Import if that key does not exist in the other table the mysql import will throw errors .
If you remove the FOREIGN KEY flag you would be able to import that table
refer to MYSQL manual
on Foreign Keys
Foreign keys will check if the other table has already that element that you try to enter.
What you can do for the import temporarily
use FOREIGN_KEY_CHECKS
Before the import run
SET FOREIGN_KEY_CHECKS=0;
and When it is finished
SET FOREIGN_KEY_CHECKS=1;
Or
use DISABLE KEYS:
ALTER TABLE table_name DISABLE KEYS;
and when the import is finished:
ALTER TABLE table_name ENABLE KEYS;
Of course you have to change table_name
I'm new to MySQL and databases in general. I've been tasked with manually moving an old database to a new one of a slightly different format. The challenges include transferring certain columns from a table in one database to another database of a similar format. This is made further difficult in that the source database is MyISAM and the destination is InnoDB.
So I have two databases, A is the source and B is the destination, and am attempting to copy 'most' of a table to a similar table in the destination database.
Here is the command I run:
INSERT INTO B.article (id, ticket_id, article_type_id,
article_sender_type_id, a_from, a_reply_to, a_to, a_cc, a_subject,
a_message_id, a_in_reply_to, a_references, a_content_type, a_body,
incoming_time, content_path, valid_id, create_time, create_by,change_time,
change_by)
SELECT id, ticket_id, article_type_id, article_sender_type_id,
a_from, a_reply_to, a_to, a_cc, a_subject, a_message_id, a_in_reply_to,
a_references, a_content_type, a_body, incoming_time, content_path,
valid_id, create_time, create_by, change_time, change_by
FROM A.article
WHERE id NOT IN ( 1 );
Error:
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`helpdesk`.`article`, CONSTRAINT `FK_article_ticket_id_id` FOREIGN KEY (`ticket_id`) REFERENCES `ticket` (`id`))
The reason for making the command so wordy is that the source has several columns that were unnecessary and so were pruned out of the destination table. The WHERE id NOT IN ( 1 ) is there so that the first row is not copied (it was initialized in both databases and MySQL throws an error if they both have the same 'id' field). I can't tell by the error if it expects 'ticket_id' to be unique between rows, which it is not, or if it is claiming that a row does not have a ticket_id and so can not be copied which is what the error seems to most often be generated by.
I can post the tables in question if that will help answer, but I am unsure of the best way to do that, so some pointing in the right direction there would be helpful as well.
Posts I looked at before:
For forming the command
For looking at this error
Thanks!
You'll want to run a SHOW CREATE TABLE on your destination table:
SHOW CREATE TABLE `B`.`article`;
This will likely show you that there is a foreign key on the table, which requires that a value exist in another table before it can be added to this one. Specifically, from your error, it appears the field ticket_id references the id field in the ticket table. This introduces some complexity in terms of what needs to be migrated first -- the referenced table (ticket) must be populated before the referencing table (article).
Without knowing more about your tables, my guess is that you haven't migrated in the ticket table yet, and it is empty. You'll need to do that before you can fill in the B.article table. It is also possible that your data is corrupt and you need to find which ticket ID is present in the article data you're trying to send over, but not present in the ticket table.
Another alternative is to turn off foreign key checks, but if possible I would avoid that, since the purpose of foreign keys is to ensure data integrity.
Given the schema:
What I need is having every user_identities.belongs_to reference an users.id.
At the same time, every users has a primary_identity as shown in the picture.
However when I try to add this reference with ON DELETE NO ACTION ON UPDATE NO ACTION, MySQL says
#1452 - Cannot add or update a child row: a foreign key constraint fails (yap.#sql-a3b_1bf, CONSTRAINT #sql-a3b_1bf_ibfk_1 FOREIGN KEY (belongs_to) REFERENCES users (id) ON DELETE NO ACTION ON UPDATE NO ACTION)
I suspect this is due to the circular dependency, but how could I solve it (and maintain referential integrity)?
The only way to solve this (at least with the limited capabilities of MySQL) to allow NULL values in both FK columns. Creating a new user with a primary identity would then look something like this:
insert into users (id, primary_identity)
values (1, null);
insert into identities (id, name, belongs_to)
values (1, 'foobar', 1);
update users
set primary_identity = 1
where id = 1;
commit;
The only drawback of this solution is that you cannot force that a user has a primary identity (because the column needs to be nullable).
Another option would be to change to a DBMS that supports deferred constraints, then you can just insert the two rows and the constraint will only be checked at commit time. Or use a DBMS where you can have a partial index, then you could use the solution with an is_primary column
I would not implement it this way.
Remove the field primary_identity from table users, and the add an additional field to table user_profiles called is_primary, and use this rather as the indicator of a primary profile
This will prevent having NULLs for FKs, but still does not enforce for primary profile to exists -- that has to be managed by application.
Note the alternate key (unique index) {UserID, ProfileID} on Profile table and matching FK on PrimaryProfile.
The problem seems to be that you are trying to keep the primary identity information in the user_identities table.
Instead, I suggest you put the primary user info (name/email) into the users table. Do not foreign key to the user_identities table.
Only foreign key from the user_identities table
All constraints will now work ok as they are only one way.
user_identities cannot be entered unless the primary user (in table users) is present. Similarly the primary user should not be deletable where there are existing child identities (in user_identities).
You might want to change the name of the tables to "primary_users" and "secondary_users" to make it obvious what is going on.
Does that sound okay?
This question was raised at How to drop tables with cyclic foreign keys in MySQL from the delete side of things, but I think that one of the answers is applicable here as well:
SET foreign_key_checks = 0;
INSERT <user>
INSERT <user identity>
SET foreign_key_checks = 1;
Make that a transaction and commit it all at once. I haven't tried it, but it works for deletes, so I don't know why it wouldn't work for inserts.
I've not used it, but you could try INSERT IGNORE. I'd do the two of those, one for each table, such that once they are both done, referential integrity is maintaing. If you do them in a transaction, you can roll back if there is a problem inserting the second one.
Since you're ignoring constraints with this feature, you should do that check in program code instead, otherwise you may end up with data in your database that ignores your constraints.
Thanks to #Mihai for pointing out the problem with the above. Another approach would be to disable constraints whilst you do inserts, and re-enable them afterwards. However, on a large table that might produce more overhead than is acceptable - try it?
I feel like I'm being stupid, but I can't find anywhere on the phpMyAdmin interface to add constraints to foreign keys e.g. CASCADE ON DELETE
I've looked for similar questions on here and on the phpMyAdmin wiki but I can't find anything about it.
I realise I could do this via the query interface, but I'd like to know how to do it through the graphical interface.
First, you should have your storage engine as InnoDB. Then select a table and go to 'Structure' tab.
Under the table you will see 'Relation view', click it. From there you could add constraints.
CASCADE
Whenever rows in the master (referenced) table are deleted (resp. updated), the respective rows of the child (referencing) table with a matching foreign key column will get deleted (resp. updated) as well. This is called a cascade delete (resp. update[2]).
RESTRICT
A value cannot be updated or deleted when a row exists in a foreign key table that references the value in the referenced table. Similarly, a row cannot be deleted as long as there is a reference to it from a foreign key table.
NO ACTION
NO ACTION and RESTRICT are very much alike. The main difference between NO ACTION and RESTRICT is that with NO ACTION the referential integrity check is done after trying to alter the table. RESTRICT does the check before trying to execute the UPDATE or DELETE statement. Both referential actions act the same if the referential integrity check fails: the UPDATE or DELETE statement will result in an error.
SET NULL
The foreign key values in the referencing row are set to NULL when the referenced row is updated or deleted. This is only possible if the respective columns in the referencing table are nullable. Due to the semantics of NULL, a referencing row with NULLs in the foreign key columns does not require a referenced row.
Firstly, you should choose storage engine as InnoDB.
Follow this way: click database_name -> More -> Designer
I have been trying to learn from reading tutorials online and stuff but I just can't put my finger on it.
I have 2 tables at the moment (i'll have a lot more later on as I build my application) so I want to knock out this issue before expanding and coding.
I have my tables set to use InnoDB and I have each table related to each other by using user_id as foreign keys.
If i issue a DELETE query on the main users table, how can i get all records from other tables that are linked to the user_id field get deleted as well?
I know its simple, but I think I just need to ask the question myself so I can understand the answer rather than reading the answer... heh
thank a lot for any help.
Since they are InnoDB tables with proper FK relationships, you can simply use ON DELETE CASCADE in the foreign key definition. For example in one of the related tables:
FOREIGN KEY (user_id) REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE
However, this requires altering your existing schema to modify the foreign keys.
See the MySQL FOREIGN KEY docs for complete information.
You can cascade the DELETE using a DELETE trigger or using the technique Michael suggested, or you can manually write enough DELETE statements (deleting the entities from the bottom of the hierarchy upwards so you don't violate the foreign key constraints) though the latter is clearly not an ideal solution in terms of maintenance.
You may wish to use the TRIGGER approach if you want to fine tune the delete process (e.g. in case you don't want to destroy certain data related to the foreign key, or if you wanted to move it elsewhere or associate it to a different ID).
this is mysql example
ALTER TABLE table_with_foregin_key ADD FOREIGN KEY ( foreign_key_column )
REFERENCES table_name (
user_id
) ON DELETE CASCADE ON UPDATE CASCADE;