IntegrityError: foreign key violation upon delete - sql

I have Order and Shipment model. Shipment has a foreign key to Order.
class Order(...):
...
class Shipment()
order = m.ForeignKey('Order')
...
Now in one of my views I want do delete order object along with all related objects. So I invoke order.delete().
I have Django 1.0.4, PostgreSQL 8.4 and I use transaction middleware, so whole request is enclosed in single transaction.
The problem is that upon order.delete() I get:
...
File "/usr/local/lib/python2.6/dist-packages/django/db/backends/__init__.py", line 28, in _commit
return self.connection.commit()
IntegrityError: update or delete on table "main_order" violates
foreign key constraint "main_shipment_order_id_fkey" on table "main_shipment"
DETAIL: Key (id)=(45) is still referenced from table "main_shipment".
I checked in connection.queries that proper queries are executed in proper order. First shipment is deleted, after that django executes delete on order row:
{'time': '0.000', 'sql': 'DELETE FROM "main_shipment" WHERE "id" IN (17)'},
{'time': '0.000', 'sql': 'DELETE FROM "main_order" WHERE "id" IN (45)'}
Foreign key have ON DELETE NO ACTION (default) and is initially deferred. I don't know why I get foreign key constraint violation.
I also tried to register pre_delete signal and manually delete shipment objects before delete on order is called, but it resulted in the same error.
I can change ON DELETE behaviour for this key in Postgres but it would be just a hack, I wonder if anyone has a better idea what's going on here.
There is also a small detail, my Order model inherits from Cart model, so it actually doesn't have id field but cart_ptr_id and after DELETE on order is executed there is also DELETE on cart, but it seems unrelated? to the shipment->order problem so I simplified it in the example.

DETAIL: Key (id)=(45) is still
referenced from table "main_shipment".
There is still a record referencing to id 45. You did delete record 17 in main_shipment before, but there might be others as well. You have to delete all records in main_shipment referencing to id 45 in main_order. If not, the database protects you from doing harm to your data.

Related

If I got many to many relationship data first, how do I insert them to my table?

Say I have a customer table, a product table and an order table to record who buys what, the order table basically has 2 foreign keys, customer_id & product_id.
Now I got the order information first, within in it I can't find the customer information in my local database. As it turns out this is a new customer, whose information will come later from another thread/queue. To make things even worse the customer id I got from the order information is not the same one I used locally. My local customer id is INTEGER PRIMARY KEY (I do record that "true customer id" as another column and set index on it)
So how I do record this order information? I can come up with some clumsy solution, e.g. if I can't find contact info, I insert a record for it first. Later after I get the real information for this customer, I update customer & order table. But I was wondering is there any "standard" way for the situation like this?
Inserting NULL values, and then updating with the real values later, is simple and will work (if you don't have a NOT NULL constraint).
You should use a transaction so that concurrent users don't see the incomplete data.
You could use deferred foreign key constraints:
If a statement modifies the contents of the database such that a deferred foreign key constraint is violated, the violation is not reported immediately. Deferred foreign key constraints are not checked until the transaction tries to COMMIT. For as long as the user has an open transaction, the database is allowed to exist in a state that violates any number of deferred foreign key constraints.
However, deferred foreign key constraints are useful only if you are inserting values that violate the constraint; a NULL value is not considered a FK violation.

Issue with re-adding a relationship in SQL Server

I'm in a bit of a jam. I have this table with a few of relationships, one of which was referencing itself (let's call this relationship A).
I needed to delete some rows from this table but because one of my relationships was referencing itself I was unable to do so. Therefore, I simply deleted relationship A and saved the table.
After deleting the rows that I wanted to delete, I attempted to re-add relationship A, however I am now presented with the following error message.
'T_FormulaireQuestion' table
Unable to create relationship 'FK_T_FormulaireQuestion_T_FormulaireQuestion'.
The ALTER TABLE statement conflicted with the FOREIGN KEY SAME TABLE constraint "FK_T_FormulaireQuestion_T_FormulaireQuestion". The conflict occurred in database "VilleG", table "dbo.T_FormulaireQuestion", column 'intFormulaireQuestionID'.
I believe what this message is saying is that my relationship B is causing a conflict when trying to re-add relationship A.
My question is, how can I re-add relationship A? Do I have to delete relationship B, re-add relationship A and finally re-add relationship B?
I'd prefer not have to delete the entire table as I have important data within it.
Please use the following image as a reference.
Thank you!
You could not delete rows because that would have violated the relationship. After forcing the delete to run, the relationship is, of course, violated... You have destroyed data integrity. Your delete operation was invalid. You silenced the error message but you still executed the error.
Fix the data before adding the constraint back. Probably, this means deleting any rows that are dependent on the now deleted rows in T_FormulaireQuestion. You have to figure out which rows have no matching row in T_FormulaireQuestion and delete them.
You can add the constraint back once it is no longer violated. Note that any violation of the constraint implies that your data is invalid. You should fix this state.

Delete when a Foreign key exist - is there a way to get the id of the key that violated the Foreign key (EF)

I am working with entity framework.
I have table A & B in 1:n.
Say I delete many rows in A and one of the a key-row in table A has one or many rows in table B.
I get sqlException with the following text
The DELETE statement conflicted with the REFERENCE constraint "FK_A_B".
The conflict occurred in database "DCDCommunity", table "Template.Template",
column 'ApplicationTypeID'. The statement has been terminated.
Is there a way to get the id of the key that violated the Foreign key.
Important EDIT:
I know I can check if B has rows.
But that will be prone to persistency problems.
(Lets say that another insert request is issued right after the check. )
By not checking and letting the database throw an exception I let him deal with the persistency (especially when running on several machines)
Now - If I only had more data in the SQL exception I could rely on this mechanism only.
You cannot delete Rows from A (your primary key table) where there are related records in B (foreign table). That violates the relationship. Therefore you need to first delete them from B and then delete from A. Or you can do ON DELETE CASCADE. Pls Check out this example here

Changing a record in a table (sql server) that has foreign keys?

Does anyone know if there is a quicker way of editing a record that has foreign keys in a table (in sql server).. i will explain.. i have approx 5 tables that have there own ID but are linked together using a foreign key...
Hence i needed to change the foreign key (the contract number in my case), but i had to copy each record to a new record and edit it that way...
As if i try to edit the contract number it gives me the standard error of being associated and violates a foreign key etc
Surly there must be a better way?
ANy ideas?
are you talking about changing the PK and then updating all the Fks? In that case enable cascade updates and this will be done automagically
same with deletes, you enable cascade deletes
ON DELETE CASCADE
Specifies that if an attempt is made to delete a row with a key referenced by foreign keys in existing rows in other tables, all rows containing those foreign keys are also deleted. If cascading referential actions have also been defined on the target tables, the specified cascading actions are also taken for the rows deleted from those tables.
ON UPDATE CASCADE
Specifies that if an attempt is made to update a key value in a row, where the key value is referenced by foreign keys in existing rows in other tables, all of the foreign key values are also updated to the new value specified for the key. If cascading referential actions
I'm not an SQL expert, but can't you set something like ON UPDATE CASCADE to automatically update the foreign key when the primary key is changed?
Or try disabling the integrity constraint, do your changes and attempt to re-enable the constraint. Basically, if you didn't do it right you will get an error then (can't enable a constraint that would be violated).

When to use "ON UPDATE CASCADE"

I use ON DELETE CASCADE regularly but I never use ON UPDATE CASCADE as I am not so sure in what situation it will be useful.
For the sake of discussion let see some code.
CREATE TABLE parent (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
);
CREATE TABLE child (
id INT NOT NULL AUTO_INCREMENT, parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON DELETE CASCADE
);
For ON DELETE CASCADE, if a parent with an id is deleted, a record in child with parent_id = parent.id will be automatically deleted. This should be no problem.
This means that ON UPDATE CASCADE will do the same thing when id of the parent is updated?
If (1) is true, it means that there is no need to use ON UPDATE CASCADE if parent.id is not updatable (or will never be updated) like when it is AUTO_INCREMENT or always set to be TIMESTAMP. Is that right?
If (2) is not true, in what other kind of situation should we use ON UPDATE CASCADE?
What if I (for some reason) update the child.parent_id to be something not existing, will it then be automatically deleted?
Well, I know, some of the question above can be test programmatically to understand but I want also know if any of this is database vendor dependent or not.
Please shed some light.
It's true that if your primary key is just an identity value auto incremented, you would have no real use for ON UPDATE CASCADE.
However, let's say that your primary key is a 10 digit UPC bar code and because of expansion, you need to change it to a 13-digit UPC bar code. In that case, ON UPDATE CASCADE would allow you to change the primary key value and any tables that have foreign key references to the value will be changed accordingly.
In reference to #4, if you change the child ID to something that doesn't exist in the parent table (and you have referential integrity), you should get a foreign key error.
Yes, it means that for example if you do UPDATE parent SET id = 20 WHERE id = 10 all children parent_id's of 10 will also be updated to 20
If you don't update the field the foreign key refers to, this setting is not needed
Can't think of any other use.
You can't do that as the foreign key constraint would fail.
I think you've pretty much nailed the points!
If you follow database design best practices and your primary key is never updatable (which I think should always be the case anyway), then you never really need the ON UPDATE CASCADE clause.
Zed made a good point, that if you use a natural key (e.g. a regular field from your database table) as your primary key, then there might be certain situations where you need to update your primary keys. Another recent example would be the ISBN (International Standard Book Numbers) which changed from 10 to 13 digits+characters not too long ago.
This is not the case if you choose to use surrogate (e.g. artifically system-generated) keys as your primary key (which would be my preferred choice in all but the most rare occasions).
So in the end: if your primary key never changes, then you never need the ON UPDATE CASCADE clause.
Marc
A few days ago I've had an issue with triggers, and I've figured out that ON UPDATE CASCADE can be useful. Take a look at this example (PostgreSQL):
CREATE TABLE club
(
key SERIAL PRIMARY KEY,
name TEXT UNIQUE
);
CREATE TABLE band
(
key SERIAL PRIMARY KEY,
name TEXT UNIQUE
);
CREATE TABLE concert
(
key SERIAL PRIMARY KEY,
club_name TEXT REFERENCES club(name) ON UPDATE CASCADE,
band_name TEXT REFERENCES band(name) ON UPDATE CASCADE,
concert_date DATE
);
In my issue, I had to define some additional operations (trigger) for updating the concert's table. Those operations had to modify club_name and band_name. I was unable to do it, because of reference. I couldn't modify concert and then deal with club and band tables. I couldn't also do it the other way. ON UPDATE CASCADE was the key to solve the problem.
The ON UPDATE and ON DELETE specify which action will execute when a row in the parent table is updated and deleted. The following are permitted actions : NO ACTION, CASCADE, SET NULL, and SET DEFAULT.
Delete actions of rows in the parent table
If you delete one or more rows in the parent table, you can set one of the following actions:
ON DELETE NO ACTION: SQL Server raises an error and rolls back the delete action on the row in the parent table.
ON DELETE CASCADE: SQL Server deletes the rows in the child table that is corresponding to the row deleted from the parent table.
ON DELETE SET NULL: SQL Server sets the rows in the child table to NULL if the corresponding rows in the parent table are deleted. To execute this action, the foreign key columns must be nullable.
ON DELETE SET DEFAULT: SQL Server sets the rows in the child table to their default values if the corresponding rows in the parent table are deleted. To execute this action, the foreign key columns must have default definitions. Note that a nullable column has a default value of NULL if no default value specified.
By default, SQL Server appliesON DELETE NO ACTION if you don’t explicitly specify any action.
Update action of rows in the parent table
If you update one or more rows in the parent table, you can set one of the following actions:
ON UPDATE NO ACTION: SQL Server raises an error and rolls back the update action on the row in the parent table.
ON UPDATE CASCADE: SQL Server updates the corresponding rows in the child table when the rows in the parent table are updated.
ON UPDATE SET NULL: SQL Server sets the rows in the child table to NULL when the corresponding row in the parent table is updated. Note that the foreign key columns must be nullable for this action to execute.
ON UPDATE SET DEFAULT: SQL Server sets the default values for the rows in the child table that have the corresponding rows in the parent table updated.
FOREIGN KEY (foreign_key_columns)
REFERENCES parent_table(parent_key_columns)
ON UPDATE <action>
ON DELETE <action>;
See the reference tutorial.
It's an excellent question, I had the same question yesterday. I thought about this problem, specifically SEARCHED if existed something like "ON UPDATE CASCADE" and fortunately the designers of SQL had also thought about that. I agree with Ted.strauss, and I also commented Noran's case.
When did I use it? Like Ted pointed out, when you are treating several databases at one time, and the modification in one of them, in one table, has any kind of reproduction in what Ted calls "satellite database", can't be kept with the very original ID, and for any reason you have to create a new one, in case you can't update the data on the old one (for example due to permissions, or in case you are searching for fastness in a case that is so ephemeral that doesn't deserve the absolute and utter respect for the total rules of normalization, simply because will be a very short-lived utility)
So, I agree in two points:
(A.) Yes, in many times a better design can avoid it; BUT
(B.) In cases of migrations, replicating databases, or solving emergencies, it's a GREAT TOOL that fortunately was there when I went to search if it existed.
My comment is mainly in reference to point #3: under what circumstances is ON UPDATE CASCADE applicable if we're assuming that the parent key is not updateable? Here is one case.
I am dealing with a replication scenario in which multiple satellite databases need to be merged with a master. Each satellite is generating data on the same tables, so merging of the tables to the master leads to violations of the uniqueness constraint. I'm trying to use ON UPDATE CASCADE as part of a solution in which I re-increment the keys during each merge. ON UPDATE CASCADE should simplify this process by automating part of the process.
To add to other great answers here it is important to use ON UPDATE CASCADE (or on DELETE CASCADE...) cautiously. Operations on tables with this specification require exclusive lock on underlaying relations.
If you have multiple CASCADE definitions in one table (as in other answer), and especially multiple tables using same definitions, and multiple users updating, this can create a deadlock when one process acquires exclusive lock on first underlaying table, other exclusive lock on second, and they block out each other by none of them being able to get both (all) exclusive locks to perform operation.