Laravel 4.0 cascade delete and polymorphic relations - mysql

I am using the Eloquent plymorphic relations and the ON DELETE CASCADE option of mysql, and am afraid of how my data will stay consistent over time. Let me explain:
If I have a model Room which contains furnitures of several types (morphMany of Table, Chair, Couch...), and that I decide to delete it, his related furnitures won't get deleted.
To solve this issure I handled the deletion of the related furnitures in the delete event of the Room model, but this event won't necessarily get fired all the time.
Let's say that I have an other model called House, containing several rooms (hasMany). If I decide to delete it, its related models will deleted by mysql with the ON DELETE CASCADE option. I will then stay with data in my tables tables, chairs, couchs that are not relevant anymore, and not related to any row of the rooms table anymore.
So what is the best way to keep a database consistent with ON DELETE CASCADE and the Eloquent's polymorphic relations?

If you're using the raw database (cascading) approach, that bypasses Eloquent and it becomes impossible to do what you want.
Set up a deleted event for House which iterates through all its Rooms and deletes those, which again triggers the Room's deleted events.

Related

Prevent delete if object in some collection

In SQLAlchemy is it possible to prevent (or specifically raise a custom Exception) the deletion of an object that is part of a collection in a many-to-many relationship.
For example below I have a Party and Person. Any Party can have many Persons and any Person can go to many Parties.
If a Person is recorded as going to one or more Parties I want to prohibit that Person from being deleted.
party_person_ass_table = db.Table('party_person', db.Model.metadata,
db.Column('party_id', db.ForeignKey('party.id'), primary_key=True),
db.Column('person_id', db.ForeignKey('person.id'), primary_key=True))
class Party(db.Model):
...
people = db.relationship('Person', secondary=party_person_ass_table, back_populates='parties')
class Person(db.Model):
...
parties = db.relationship('Party', secondary=party_person_ass_table, back_populates='people')
Reading the docs it seems cascade deleting from the secondary table is automatically set (https://docs.sqlalchemy.org/en/13/orm/basic_relationships.html). I wonder if a solution to generate an IntegrityError would be to add a nullable=False to the person_id column in the secondary association table and then somehow prevent a cascade delete from impacting the secondary table?
adding the tag viewonly=True to:
parties = db.relationship('Party', secondary=party_person_ass_table, back_populates='people', viewonly=True)
decouples Person from the party_person_ass_table and when modified it does not automatically delete the row in the association table, which breaks database integrity.
This is also why the commented 'ON DELETE RESTRICT' fails because it isnt an inherent cascade, but SQLAlchemy specifically deletes these rows as part of its function so these hooks aren't called in the usual way.

Spring Roo - many to many relationship deletes and inserting at every update- How to change this behavior

I have two entities created.
Entity BOOK, Entity AUTHOR having many to many relationship.
In the db I got tables [book,author, book_author].
Table book_author maps the many to many relationship.
When I update authors of a book all related relationship records in book_author
get deleted and then get re-inserted.
Is there a way to alter this behavior to do updates as necessary, without doing
delete and re-insert.
By the no modification have been done manually. All the code have been done with ROO.
It is the default behavior if "List" is used as the collection to keep relationship
in the entity level. Instead we can use a "Set" which will make updates and deletes as
necessary without doing delete and re-insert.
This is clearly explained in the following article.
http://assarconsulting.blogspot.com/2009/08/why-hibernate-does-delete-all-then-re.html

MySQL Nested FOR EACH in a single trigger instead of multiple triggers

Lets say I have 3 tables:
meals
courses
ingredients
Where meals have several courses and courses have several ingredients.
Right now if I delete a meal, there is a trigger to delete every courses linked to that meal, and a second trigger that will delete every ingredients linked to each course.
Is there a way to do this in a single trigger with say a FOR EACH inside a FOR EACH? Surely there is a way, I'm just not good enough with triggers. I searched for "nested triggers", "nested for each", maybe I'm looking at the wrong thing.
Please don't tell me I should not delete a course after deleting a meal as it might be used for another meal, same with ingredients. This is only a simplified example of what I'm really doing.
I would suggest you to use a foreign_key CONSTRAINT with ON DELETE CASCADE for both tables, but it will depend if you are using InnoDB or MyIsam engine.
See an example here: How do I use on delete cascade in mysql?

In MySQL, why do I have to define ForeignKey relationships?

Why can't I just leave those relationships out?
What's the point of them?
I can stil run queries and treat them like it a relationship myself...
Yes, you can always leave the foreign key constraints out but then you will be responsible about the integrity of your data. If you use foreign key constraints, then you won't have to worry about the referential integrity among tables. You can read more about referential integrity from Wikipedia. I will also try to explain it with an example below.
Think of a shopping cart scenario. You have three tables: item, shopping_cart and shopping_cart_item. You can choose not to define any relationship between these tables, that's fine for any SQL solution. When user starts shopping, you create a shopping cart by adding a shopping_cart entry. As user adds items to his shopping cart, you save this information by adding rows to shopping_cart_item table.
One problem may occur at this step: If you have a buggy code that assigns incorrect shopping_cart_id's to shopping_cart_items, then you will definitely end up with incorrect data! Yes, you can have this case even with a foreign key constraint if the assigned id actually exists in the shopping_cart table. But this error will be more detectable when a foreign key exists since it would not insert shopping_cart_item record when the foreign key constraint fails.
Let's continue with the assumption that your code is not buggy and you won't have first type of referential integrity. Then suddenly a user wants to stop shopping and delete the cart and you chose to implement this case by deleting the shopping_cart and shopping_cart_item entries. Then you will have to delete entries in both tables with two separate queries. If something goes wrong after you delete shopping_cart entries, then you will again have a referential integrity problem: You will have shopping_cart_items that are not related to any shopping_cart. You will then have to introduce transaction managing, try to provide meaningful data to your business logic about the error happened in data access layer, etc..
In this type of scenario's, foreign keys can save life. You can define a foreign key constraint that will prevent insertion of any sort of incorrect data and you can define cascade operations that will automatically perform deletion of related data.
If there is anything unclear, just leave a comment and I can improve the answer.
Apart from what the others have said about why you technically want (actually: need) them:
foreign key constraints also document your model.
When looking at a model without FK constraints you have no idea which table relates to which. But with FK constraints in place you immediately see how things belong together.
You create FOREIGN KEYs to instruct the database engine to ensure that you never perform an action on the database that creates invalid records.
So, if you create a FOREIGN KEY relationship between users.id and visits.userid the engine will refuse to perform any actions that result in a userid value in visits that does not exist in users. This might be adding an unknown userid to visits, removing an id from users that already exists in visits, or updating either field to "break" the relationship.
That is why PRIMARY and FOREIGN KEYs are referred to as referential integrity constraints. The tell your database engine how to keep your data correct.
It doesn't allow you to enter an id which does not exist in another table, for example, if you have products and you keep owner Id, by creating a foreign key ton the owner id to id field of the owners table, you do not allow users to create an object record which has an owner id which does not exist in the owner table. such things are called referential intergrity.
The foreign key constraint helps you ensure referential integrity.
If you delete a row in one table, mysql can automatically delete all rows in other tables that the deleted row refers to via the foreign key. You can also make it reject the delete command.
Also when you try to insert a row, mysql can automatically create new rows in other tables, so the foreign key does not refer to nothing.
That is what referential integrity is all about.
Databases can be affected by more than just the application. Not all data changes go through the application even if they are supposed to. People change stuff directly on the database all the time. Rules that need to apply to all data all the time belong on the database. Suppose you can update the prices of your stock. That's great for updating anindividual price. But what happens when the boss decides to raise all prices by 15%. No one is going to go through and change 10,000 prices one at a time through the GUI, they are going to write a quick SQL script to do the update. Or suppose two suppliers join together to have one company and you want to change all of thie items to be the new company. Those kinds of changes happen to databases every day and they too need to follow the rules for data integrity.
New developers may not know about all the places where the foreign key relationships should exist and thus make mistakes which cause the data to be no longer useful.
Databases without foreign key constraints have close to a 100% chance of having bad data in them. Do you really want to have orders where you can't identify who the customers were?
THe FKS will prevent you from deleting a customer who has orders for instance or if you use a natural key of company_name and the name changes, all related records must be changed with the key change.
Or suppose you decide to put a new GUI together and dump the old one, then you might have to figure out all the FK relationships again (because you are using a different datalayer or ORM) and the chances are you might miss some.
It is irresponsible in the extreme to not put in FK relationships. You are risking the lifeblood of your company's business because you think it is a pain to do. I'd fire you if you suggested not using FKs because I would know I couldn't trust my company's data to you.

Delete object and its many-to-many relation

I am trying to delete an object that sometimes has a many-to-many relation. The code I use now is:
db.DeleteObject(registeredDevice);
db.SaveChanges();
This ofcourse just removes the registeredDevice. But usually this device has a many-to-many relation to a project in the database. When trying to delete the device in that scenario it will give an error.
The DELETE statement conflicted with the REFERENCE constraint
What I need to do is remove the device and its relation (the entry in the many-to-many table, not the project it is related to). How do In do this with LINQ ?
To remove everything, you need to make sure all the data is loaded. Basically, linq to sql has to know about the data it is deleting before hand to make the best judgement on how to delete it.
Hoep that helps