SQL Server 2005, Enforce Foreign Key Constraint and Cascade Delete - sql

I am using SQL Server 2005 and I have to relationships going into one table. I had to turn off " Enforce Foreign Key Constraints" because I have 2 relationships going into the same table.
However I want to put cascade delete on.
I thought if I have cascade delete on both of these relationships and if I say deleted something from on of these tables it would cascade and delete into the other table.
However it does not seem to work that way and I am wondering is it because I have the foriegn key constraint off?
If this is the case how can I get around this?

You've gotta have a fk constraint to enforce cascade delete. how sql server know what to delete otherwise?

I'm not clear on why you needed to disable the foreign key constraints in the first place. You can have many relationships to the same table that all enforce referential integrity. However, if you have two relations to the same parent table in the same child table, you can only have cascade update or cascade delete enabled on one of them.
TBH, I cannot think of a situation where I would want a relationship but wouldn't want it enforced. You should always fix the data and enforce the relation so that the data cannot get corrupted.
This is actually a situation where funneling data access through stored procedures helps. If you forced people to only delete through a stored procedure, you could enforce the cascade delete in the procedure without having to enforce in the DRI.

SQL server will not allow multiple cascade paths. To get around this, add 'FOR DELETE' triggers to each additional path.
ALTER TRIGGER [dbo].[trgMyTriggerName] ON [dbo].[tblMyTable] FOR DELETE AS
SET NOCOUNT ON
DELETE FROM tblMySubTable
WHERE MySubTable_Parent_ID IN (SELECT MyTable_ID FROM deleted)
You will still want to add the foreign key, just set 'Enforce Foreign Key Constraint' to No and make your Delete Rule and Update Rule take no action. This allows you to use all the goodness of Foreign Keys (intellisense, Entity framework etc).

Related

Alternative of Cascade Delete in SQL Server

I wanted to Delete all the records from all the table where there is reference of my primary table is present.
I know we have Cascade Delete option available where we can create/alter tables to assign cascade delete and perform this,
But I have a very complex data base with huge number of reference tables so I am looking for any alternative or other way I can achieve my target?

Inserting new record and skip if foreign key conflict in sql server 2008 R2

I have the problem similar to this one SQL Server foreign key conflict in a multi values statement? However, in sql server 2008.
While I am reading data from csv file, there is some id already not exist in parent and thus return this error:
INSERT statement conflicted with the FOREIGN KEY constraint
May I know if there is a way similar to MySQL insert ignore. Such that I can simply skip the problematic data.
I accept that if there is no method other than creating a stored procedure with a new temp table (insert into a table without foreign key first, and then re-insert with where foreign_id exists in (select id from parent)).
As I really cannot find any in documentation, asking for ensuring I didn't miss anything.
One general solution which comes to mind would be to temporarily turn off the foreign key constraints, and do the insert. Then, afterwards, you may run a cleanup script/query to remove or rectify child records which are pointing to parents which do not exist. Once your data is in good shape, then turn on the foreign key constraints again.
Read How can foreign key constraints be temporarily disabled using T-SQL? to learn how to disable/enable a foreign key constraint for a single table:
ALTER TABLE MyTable NOCHECK CONSTRAINT MyConstraint -- disable
ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT MyConstraint -- enable

SQL Server 2016 Cannot add system versioning to relationship table

The SQL Server 2016 system versioning is cool. I am using the free Developer version. Thanks MS!
I am unable to figure out if it will give me versioning of many to many relationships. I have a User object that has a collection of Roles and vice versa. Entity Framework has generated the UserRoles table that holds the relationship between User and Roles. I was able to turn on system versioning for the User and Roles tables using this article http://sqlhints.com/tag/modify-existing-table-as-system-versioned-temporal-table/.
But, I am not able to turn on for UserRoles. I get an error
Setting SYSTEM_VERSIONING to ON failed because table has a FOREIGN KEY with cascading DELETE or UPDATE.
Does this mean we cannot know the versioning for many-many relationships?
For eg.
on 6/1 - User1 had role1 and role2, but
on 6/4 - User1's role changed to role1 and role3
So, if I wanted to know the state of the user on 6/1, I thought that's possible only by turning on system versioning on UserRoles, but that's not working.
Is this doable or not supported by SQL Server 2016? If not, is there any other way this can be accomplished?
It's important to notice that the limitation of using CASCADE on FOREIGN KEY constraints in temporal tables is applicable only to SQL Server 2016. In SQL Server 2017, this limitation doesn't exist anymore.
This is the relevant part from the official documentation:
ON DELETE CASCADE and ON UPDATE CASCADE are not permitted on the
current table. In other words, when temporal table is referencing
table in the foreign key relationship (corresponding to
parent_object_id in sys.foreign_keys) CASCADE options are not allowed.
To work around this limitation, use application logic or after
triggers to maintain consistency on delete in primary key table
(corresponding to referenced_object_id in sys.foreign_keys). If
primary key table is temporal and referencing table is non-temporal,
there's no such limitation.
> NOTE: This limitation applies to SQL Server 2016 only. CASCADE options
are supported in SQL Database and SQL Server 2017 starting from CTP
2.0.
Sounds like it's the ON UPDATE CASCADE or ON UPDATE DELETE foreign key that's the issue. Remove the cascading and replace that with a delete proc that knows and handles the proper relationships and you should be fine.
Personally, I like knowing what my deletes/updates are doing rather than trusting the relationships to handle all of them. I can see potential locking issues as well as know that there are times I really want to prevent an update or delete rather than letting it cascade through all of the tables unseen.
ON DELETE CASCADE and ON UPDATE CASCADE are not permitted on the current table. In other words, when temporal table is referencing table in the foreign key relationship (corresponding to parent_object_id in sys.foreign_keys) CASCADE options are not allowed. To work around this limitation, use application logic or after triggers to maintain consistency on delete in primary key table (corresponding to referenced_object_id in sys.foreign_keys). If primary key table is temporal and referencing table is non-temporal, there’s no such limitation.

Delete Value with Relational Table Trigger vs

How do you delete values with a relational database for connected tables.
Example of Movie Database:
Movie Table -> Movie_has_Genre Table -> Genre Table
If I delete a Movie I would want to delete all the rows of Movie_has_Genre table where the foreign key is the same as the id from the movie table.
Should I be using a Trigger on the Movie table (on delete... do a delete on the relational table) or is there some other built in function to handle this?
I just vaguely recall there was another way to do this but cannot remember what it was called.
You use the cascade delete statement. It's syntax looks like this:
ALTER TABLE dbo.T2
ADD CONSTRAINT FK_T1_T2_Cascade
FOREIGN KEY (keyId) REFERENCES dbo.T1(keyId) ON DELETE CASCADE
The complete syntax is: here
There is an option in SQL Server to do this automatically via CASCADE settings as already shown.
This is a really handy option but make sure you don’t apply it to all of your tables that have foreign key references as it might cause unexpected loss of data. Make sure to thoroughly analyze weather this won’t cause any damage.
Another option is to use multiple delete statements starting from the tables that are referenced first.

Create constraint alter table invalid

I had to modify an existing constraint so it would cascade updates and deletes.
To do this I first removed the constraint and was planning on adding it (through an ALTER TABLE) but this fails.
When I commit the query below it gives me the error 'ORA-01735: invalid ALTER TABLE option':
ALTER TABLE
PARAM
ADD CONSTRAINT
FK_PARAM_PORTLET FOREIGN KEY (PORTLETID)
REFERENCES PORTLET(ID)
ON DELETE CASCADE ON UPDATE CASCADE;
Any idea what it could be? Am I overlooking something?
Oracle does not support ON UPDATE CASCADE in foreign keys.
Have a look at this question for tips: How to create a Foreign Key with "ON UPDATE CASCADE" on Oracle?
UPDATE CASCADE is not supported in Oracle. You will need to manage this via triggers.
Check Oracle statement:
Referential integrity constraints can specify particular actions to be
performed on the dependent rows in a child table if a referenced
parent key value is modified. The referential actions supported by the
FOREIGN KEY integrity constraints of Oracle are UPDATE and DELETE NO
ACTION, and DELETE CASCADE.