I have a stored procedure which runs a couple of deletes, inserts and updates for several tables.
My problem: The procedure causes key constraint violations.
Example:
DELETE FROM tableA WHERE key='1'
DELETE FROM tableB WHERE key='1'
Table B has a foreign key reference to table A, the procedure stops and I get an error message. All changes are discarded.
My question: How can I tell the procedure or server that the entry in table A is already deleted? Can I use table A from the cache for the foreign key reference comparisons?
I use a microsoft sql server.
EDIT
I'm sorry, I mixed the chronological order.
In fact, table A has the FK and its entry is the first one to be deleted.
Table B follows afterwards with no reference to table A.
Nevertheless, I get a "conflicted with the REFERENCE constraint" message.
The only explanation for this error message I have is, that the delete on table A is not committed.
EDIT
I may have found the problem. All my delete statements are enclosed in BEGIN/END.
So I have:
BEGIN
DELETE FROM tableA WHERE key='1'
DELETE FROM tableB WHERE key='1'
END
As far as I understand, such enclosed statements are run as one big statement before anything is committed.
Regards
You have two options:
To perform queries in the correct so the server will be able to execute them correctly.
You can get rid of foreign keys for those tables during the execution of the procedure.
If TABLEB has a FK from TABLEA then you must first delete fromTABLEB:
DELETE FROM tableB WHERE key='1' --Doing this will remove the row that references TABLEA
DELETE FROM tableA WHERE key='1' --TABLEA can be deleted because there are no references to the row in the other TABLE
Related
I'm adding a new job category to a database. There are something like 20 tables that use jobCategoryID as a foreign key. Is there a way to create a function that would go through those tables and set the jobCategoryID to NULL if the category is ever deleted in the parent table? Inserting the line isn't the issue. It's just for a backout script if the product owners decide at a later date that they don't want to keep the new job category on.
You need some action. First of all update the dirty records to NULL. For each table use:
Update parent_table
Set jobCategoryID = NULL
WHERE jobCategoryID NOT IN (select jobCategoryID FROM Reerenced_tabble)
Then set delete rule of foreign keys to SET NULL.
If you care about performance issue, follow the below instruction too.
When you have foreign key but dirty records it means, that these constraints are not trusted. It means that SQL Optimizer can not use them for creating best plans. So run these code to see which of them are untrusted to optimizer:
Select * from sys.foreign_keys Where is_not_trusted = 1
For each constraint that become in result of above code edit below code to solve this issue:
ALTER TABLE Table_Name WITH CHECK CHECK CONSTRAINT FK_Name
I have two tables: Group and Schedule.
The Group table consists of columns: Group_Name, No_of_member.
The Schedule table consists of column: Group_Name, Schedule_Date.
A group can have many schedules.
I'm trying to create a trigger which deletes all corresponding records from the Schedule table when a particular record is deleted from the Group table. I have written a trigger as:
CREATE OR REPLACE TRIGGER group_test
AFTER DELETE ON Group
FOR EACH ROW
BEGIN
DELETE FROM Schedule WHERE Schedule.group_name = :old.group_name;
END;
But when I try to delete a record from the group table with command: DELETE FROM Group WHERE group_name = 'AwesomeGroup'; , Oracle shows:
Table is mutating, trigger/function may not see it.
at line 2, error during execution of trigger 'group_test'
This would make sense if I was trying to delete a record from the same table in which I've created the trigger (Group in this case), but I have the trigger on Group table and I'm trying to delete the records on Schedule table. So, why does oracle keep giving me this error?
You are getting this error because you have a ON DELETE CASCADE clause on table Schedule for the foreign key on column group_name.
So naturally, when you do the DELETE on table Group, Oracle automatically follows the foreign key and go delete the records in Schedule, which makes the table change.
This is what causes your trigger group_test to dysfunction. In fact, this trigger is redundant with the ON DELETE CASCADE clause. I agree with #WernfriedDomscheit, you must choose between one of the two solutions.
i have two tables Table1 and Table2. Where table1 column primary key is referred to table2 column as foreign key.
Now i have to display a error message of constraint violation when ever i delete records from table2 which is having foreign key column of table1.
If I get it right your column A (say) in table 1 references column B (say) in table 2.
What you can do is set the ON DELETE to NO ACTION which will prevent deletion of records from table 2 if any children of it still exists in table 1.
You can can do this by:
ALTER TABLE TABLE1 ADD FOREIGN KEY (A) REFERENCES TABLE2 (B) ON DELETE NO ACTION;
You don't have a constraint violation if you delete records from the child table and not the parent. It is normal to delete child records. For instance if I have a user table and a photos tables that contains the userid from the users table, why would I want to stop that action and throw an error if I want to delete a photo? Deleting a child record doesn't also delete the parent.
If you really want to do that, then you must do it through a trigger (make sure to handle multiple record deletes) or if the FK is a required field, then simply don't grant permissions to delete to the table. Be aware that this may mean you can never delete any records even when you try to delete. A simple method may be to not have a delete function available in the application.
I suspect what you really need to a to get a better definition of what is needed in the requirements document. In over 30 years of dealing with hundreds of databases, I have never seen anyone need this functionality.
I have a table (TableB) that has a foreign key relationship with a parent table (TableA).
When I delete a record in Table A, I want to preserve referential integrity by deleting all records in TableB that reference the deleted record in TableA.
Normally I would ON DELETE CASCADE. However due to the table structure and the overprotective safeguards against multiple cascade paths in SQL Server, this is not possible for this specific relationship.
I also cannot use an INSTEAD OF trigger as TableA itself has a CASCADE foreign key relationship on it.
What I'm thinking of doing is changing the relationship between TableA and TableB to ON DELETE SET NULL, then creating an AFTER trigger to cleanup the NULL records in TableB.
Are there better ways of dealing with this scenario?
Can you change the other constraint that is preventing you from adding this one as ON DELETE CASCADE?
Can you add a DeleteMe column, then issue an UPDATE A SET DeleteMe = 1, then use an after trigger to delete Table B rows first, then the requested table A rows?
Can you split or merge tables (vertically, that is) in some way that separates their mutually exclusive dependencies?
I have two tables in my database and the t1 table primary key is uid, t2 table a foreign key name desg. now I want to delete or update this uid in one table give error that
Now row was updated. data in the row
was not committed. error
source:.netSqlclient data provider.
error message: the update statement
conflicted with the reference
constraint fk_t2_t1.the conflict occur
in the database DBname, dbo.t2,column
desg. the stsement has been
terminated.
and when I try to delete, it show this message.
executed SQl statement: delete from t1
where uid='abc'
error source:.netSqlclient data
provider. error message: the Delete
statement conflicted with the
reference constraint fk_t2_t1.the
conflict occur in the database DBname,
dbo.t2,column desg. the stsement has
been terminated.
Please tell me how to do this update and delete.
I am new to this field need help thanks in advances.
first delete the t2 table a foreign key then delete t1 table primary key is uid . this will work not vise versa
You have one or more child records in table t2 which are pointing at the master record in table t1 that you want to delete. Before you can delete your record in t1, you must delete the child records in t2.
For example:
(1) delete * from t2 where t2.desg = t1.uid;
(2) delete * from t1 where t1.uid = UID_TO_BE_REMOVED;
I would recommend reading a good reference on creating tables and performing queries for the SQL database you are using.
Good luck!