Adding constraint conflicts with itself, even though it doesn't exist yet - sql-server

I'm adding delete cascading to a Table. The Clone table has a column DeviceID that is a foreign key to the Device table's DeviceID column. So the SQL script drops the original FK constraint, and attempts to add the new one:
IF EXISTS
(
SELECT *
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_NAME = 'FK_Clone_Device'
)
BEGIN
ALTER TABLE Clone
DROP CONSTRAINT FK_Clone_Device
END
IF NOT EXISTS
(
SELECT *
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_NAME = 'FK_Clone_Device_Cascade'
)
BEGIN
ALTER TABLE Clone
ADD CONSTRAINT FK_Clone_Device_Cascade
FOREIGN KEY (DeviceID) REFERENCES Device(DeviceID) ON DELETE CASCADE
END
When I run this script, I get the following error:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_Clone_Device_Cascade". The conflict occurred in database "DevelopmentDB", table "dbo.Device", column 'DeviceID'.
Maybe I'm misunderstanding the error message, but it sounds like it's conflicting with itself. I'm confused that it happened on the Device table though.
There is an index in the Clone table on DeviceID. Would that matter?
This is on SQL SERVER R2 (Azure)

Sounds like you currently have data in the table that would violate the FK you are trying to create. One way to test this is to add "WITH (NOCHECK)" to the ALTER TABLE statement and see if it lets you create the constraint.
If it does let you create the constraint with NOCHECK, you can either leave it that way and the constraint will only be used to test future inserts/updates, or you can investigate your data to fix the FK violations.
So your example would be:
ALTER TABLE Clone WITH NOCHECK
ADD CONSTRAINT FK_Clone_Device_Cascade
FOREIGN KEY (DeviceID) REFERENCES Device(DeviceID) ON DELETE CASCADE

Related

Drop foreign key constraint in SQL Server without knowing the constraint name

I have to write a script where in I need to drop a foreign key constraint, the problem is that I do not know the constraint name.
I know I could use sp_help CHILD_TABLE_NAME to find the name of the constraint and then run ALTER TABLE CHILD_TABLE_NAME DROP CONSTRAINT CONSTRAINT_NAME to drop the foreign key constraint, But since I'm writing a script I need to do that programatically through SQL code.
The following query will give you a list of all the foreign key names on a given table. You should be able to iterate through them from there.
(Hint unless you want to drop them permanently it's better to disable them).
SELECT name AS FK_Name
FROM sys.foreign_keys
WHERE parent_object_id = OBJECT_ID('MyObjectName')

Update even though using constraints

I'm trying to update a value (small spelling error) in the SQL Server 2014 database.
I do like this:
update t_Table set funID = 'References' where funID = 'Referencies'
When doing this I get the error
The UPDATE statement conflicted with the FOREIGN KEY constraint "FK_t_Table_Language_t_Table". The conflict occurred in database "db", table "dbo.t_Table".
If updating the foreign key, I get a similar error.
Is there any way to update all values at the same time?
I have a vague memory of someone showing a way to do this in management studio but I do not recall how.
Enable update cascade on the foreign key
ALTER TABLE t_Table_Language DROP CONSTRAINT FK_t_Table_Language_t_Table
ALTER TABLE t_Table_Language ADD CONSTRAINT FK_t_Table_Language_t_Table
FOREIGN KEY (funID) REFERENCES t_Table(funID)
ON UPDATE CASCADE
EDIT:
Or the other way around, i'm not sure which table has the foreing key
ALTER TABLE t_Table DROP CONSTRAINT FK_t_Table_Language_t_Table
ALTER TABLE t_Table ADD CONSTRAINT FK_t_Table_Language_t_Table
FOREIGN KEY (funID) REFERENCES t_Table_Language(funID)
ON UPDATE CASCADE
Then do the update on the referenced table (the master table).
UPDATE t_Table_Language
SET funID = 'References'
WHERE funID = 'Referencies'

How to DELETE without ON DELETE CASCADE (conflict REFERENCE constraint)

I have a gigantic legacy database with a table that has multiple foreign keys pointing to one other table and with not a single cascade in sight, similar to sample tables below:
create table Users (
Id int primary key identity,
Name varchar(max)
)
create table Products (
Id int primary key identity,
Name varchar(max),
CreatedBy int foreign key references Users(Id),
UpdatedBy int foreign key references Users(Id)
)
insert into Users values('Bar')
insert into Users values('Baz')
insert into Products values('Foo', 1, 2)
I need to be able to to delete some of the old data, but it of course throws reference exceptions:
delete from Users where Name='Bar'
The DELETE statement conflicted with the REFERENCE constraint "FK__Products__Create__1AD3FDA4". The conflict occurred in database "Foo", table "dbo.Products", column 'CreatedBy'.
Due to the sheer complexity of the database I can't predelete all of the references, so I'm trying to add temporary foreign keys programmatically with cascades set to resolve them. However, for this particular table that has multiple foreign keys to one other table, this results in cycles or multiple cascade paths on the second UpdatedBy alter:
alter table Products add foreign key (CreatedBy) references Users(Id) on delete cascade
alter table Products add foreign key (UpdatedBy) references Users(Id) on delete cascade
Introducing FOREIGN KEY constraint 'FK__Products__Update__1DB06A4F' on table 'Products' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
How can I make delete from Users where work while maintaining referential integrity, either by somehow getting around multiple cascade path issues or otherwise?
Personally I would not do this (I would pre-delete all the referenced data and manually check the integrity). See: Can foreign key constraints be temporarily disabled using T-SQL?
Quote:
-- disable all constraints
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
Delete your data once the constraints are disabled, but remember to turn them back on again afterwards!
-- enable all constraints
EXEC sp_msforeachtable #command1="print '?'", #command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
Also note that the stored procedure sp_msforeachtable is undocumented and may disappear in future releases of SQL Server.
If you'd rather not blanket-disable constraints (perhaps you have a list of the tables that apply) then simply disable them as you can see in the code above.
ALTER TABLE [Products] NOCHECK CONSTRAINT ALL
DELETE FROM [Users] where Name='Bar'
ALTER TABLE [Products] WITH CHECK CHECK CONSTRAINT ALL
All credit goes to kristof's answer. Please up vote!

How to recheck primary/foreign key constraint for data already in the table in sql server?

I have a table in SQL Server 2005 with a foreign key and it was disable for huge data loading, and then re-enabled:
Example:
alter table table1 nocheck constraint fk_1
go
lots of inserts...
go
alter table table1 check constraint fk_1
go
Now, the question: is there a way to re-check this just inserted data?
The syntax looks a little silly with the word "check" repeated, but what you want is:
alter table table1 with check check constraint fk_1
go
Adding the "with check" option will validate existing data against the constraint. Doing this will also prevent the constraint from becoming untrusted.
If any existing data violates the constraint, you'll get an error that will look like this:
The ALTER TABLE statement conflicted with the CHECK constraint "fk_1".

Checking for a foreign key before adding it with a sql script

I have a SQL script which adds a foreign key to a table, as shown below.
ALTER TABLE [security].[Pages] WITH NOCHECK
ADD CONSTRAINT [FK_Pages_PageClasses] FOREIGN KEY ([PageClassId]) REFERENCES [security].[PageClasses]([PageClassId]) ON DELETE NO ACTION ON UPDATE NO ACTION;
Sometimes the table already has this foreign key so an error is shown when it is run from the Management Studio. Is it possible to add a query to check if the key exists before applying it? Is there a better way to do this? This must work for MS SQL 2005 and 2008.
Use the OBJECT_ID function to test for existence.
IF OBJECT_ID('[security].[FK_Pages_PageClasses]') IS NULL
ALTER TABLE [security].[Pages] WITH NOCHECK
ADD CONSTRAINT [FK_Pages_PageClasses] FOREIGN KEY ([PageClassId]) REFERENCES [security].[PageClasses]([PageClassId]) ON DELETE NO ACTION ON UPDATE NO ACTION;
You can check for the existence of the foreign key by looking in the sys.foreign_keys object catalog view:
IF NOT EXISTS(SELECT * FROM sys.foreign_keys WHERE object_id = object_id(N'[Security].[FK_Pages_PageClasses]') and parent_object_id = object_id(N'[Security].[Pages]'))
BEGIN
ALTER TABLE [security].[Pages] WITH NOCHECK
ADD CONSTRAINT [FK_Pages_PageClasses] FOREIGN KEY ([PageClassId]) REFERENCES [security].[PageClasses]([PageClassId]) ON DELETE NO ACTION ON UPDATE NO ACTION;
END

Resources