Table is mutating. Trigger may not see it (Even on different tables) - database

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.

Related

Change dependent records on delete in SQL

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

Delete trigger on Many-to-Many Table

Hello i have to create a trigger that will help me delete a User.
Example: DELETE FROM Users WHERE Users.Id = 1
I have tables that reference to the Users table, and when i try to delete from the other tables before i delete from the Users table i get this:
The DELETE statement conflicted with the REFERENCE constraint "FK_UsersChats_Users". The conflict occurred in database "cd8eb179-8ec2-41ae-aa28-46e1571ca2bf", table "dbo.UsersChats", column 'UserId'.
My Db diagram
My code so far: http://pastebin.com/45H1WGSr
You can either create a stored procedure or series of queries that deletes from the parent table, then deletes from each child table, or you can set CASCADE DELETE on the relationships so they do it automatically.

Delete, Insert, Update using table from cache?

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

Microsoft SQL server: have one auto-incrementing column update another table

I have a table of orders with orderID. I want when I create a new row in orders, and automatically have it add the same orderID to a new row in orderDetails. I got the auto incrementing to work, however whenever I try to link the two, adding cascade delete, it gives me an error.
'order' table saved successfully
'orderDetail' table
- Unable to create relationship 'FK_orderDetail_order'.
Cascading foreign key 'FK_orderDetail_order' cannot be created where the referencing column 'orderDetail.orderID' is an identity column.
Could not create constraint. See previous errors.
Which seems to be because of the fact there is no orderID at row creation. Without these two linked it's pretty hard to link an order to its information.
I am using Microsoft SQL server mgt studio. I learned via command-line MySQL, not SQL, so this whole GUI stuff is throwing me off (and I'm a tad rusty).
Your problem is that 'orderDetail.orderID' should not be an identity column (auto-incrementing). It should be based on the orderId in the Order table. You can do that in a variety of ways. If you are using stored procedures, and making separate calls to the database for the orderDetail records, have the code save the order row first, and return the newly created OrderId value, then use that value on the calls to save orderdetails. If you are making one call to a stored proc that saves the order header record and all order detail records in one call, then in the stored procd, insert the ordfer record forst, use Scope_identity() to extract the newly created orderId into a T-SQL variable,
Declare #orderId Integer
Insert Orders([Order table columns])
Values([Order table column values])
Set #orderId = scope_Identity()
and then use the value in #orderId for all inserts into the OrderDetails table...
Insert OrderDetails(OrderId, [Other OrderDetail table columns])
Values(#orderId , [Other OrderDetail table column values])
You want a AFTER INSERT trigger on the order table - in this, the newly given ID is available as NEW.orderID and can now easily be inserted into orderDetails.
Just do this via the command line. I certainly do.

foreign key data deletion should display error for primary key

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.

Resources