Create a foreign key to system tables - sql-server

I want to create table with to columns:
IdRole
IdProcedure
the idea is that IdProcedure is a FK to sys.objects.
When I create this query:
SELECT *
FROM sys.objects
WHERE type='p'
it works fine, but this one:
ALTER TABLE dbo.CORE_ProcedureXRole
ADD CONSTRAINT FK_SysProcedure
FOREIGN KEY (IdProcedure)
REFERENCES sys.objects(object_id)
tells me:
Foreign key 'FK_SysProcedure' references invalid table
'sys.objects'.

sys.objects isn't a table. It's a system view backed by data stored in proprietary SQL Server format. If you want to make sure that the stored name is correct, add a TRIGGER for update and insert to handle the checking.

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')

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

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

SQL Server 2008 foreign key confilict

We have got table which has many rows. I want create foreign key between these two tables but
I get the following error.
'CMEvent' table saved successfully;
'BaseEvent' table
Unable to create relationship 'FK_CMEvent_Oid'.
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_CMEvent_Oid". The conflict occurred in database "CMO_RestoredData", table "dbo.BaseEvent", column 'Oid'.`
I was able to duplicate this error when I had a row in the CMEvent table that did not exist in BaseEvent.
Try running this query:
SELECT *
FROM CMEvent c
WHERE NOT EXISTS (
SELECT *
FROM BaseEvent
WHERE oid = c.oid )
If you get any rows back, these will have to be deleted before you can apply the foreign key constraint.
If you need to keep these orphaned rows, you can use WITH NOCHECK to only apply the constraint to new rows.

Cannot truncate table because it is being referenced by a FOREIGN KEY constraint

I get the following message even when the table that references it is empty: "Cannot truncate table 'dbo.Link' because it is being referenced by a FOREIGN KEY constraint" Doesn't seem to make much sense why this is occurring. Any suggestions?
In SQL Server a table referenced by a FK cannot currently be truncated even if all referencing tables are empty or the foreign keys are disabled.
You need to use DELETE (may require much more logging) or drop the relationship(s) prior to using TRUNCATE and recreate them afterwards or see the workarounds on this connect item for a way of achieving this using ALTER TABLE ... SWITCH
You cannot truncate a table which has an FK constraint on it. As workaround, you could:
1/ Drop the constraints
2/ Trunc the table
3/ Recreate the constraints.
Here it is the associated T-SQL script, supposing you have 2 tables called MyTable and MyReferencedTable:
-- Remove constraint
IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE name = 'FK_MyReferencedTable_MyTable')
BEGIN
ALTER TABLE dbo.MyReferencedTable
DROP CONSTRAINT FK_MyReferencedTable_MyTable
END
-- Truncate table
TRUNCATE TABLE dbo.MyTable
-- Re-Add constraint
IF NOT EXISTS(SELECT 1 FROM sys.foreign_keys WHERE name = 'FK_MyReferencedTable_MyTable')
BEGIN
ALTER TABLE dbo.MyReferencedTable
WITH CHECK ADD CONSTRAINT [FK_MyReferencedTable_MyTable] FOREIGN KEY(ListingKey)
REFERENCES dbo.MyTable (ListingKey)
END
Execute the following query to search any constraint:
use MyDatabase
select c.name as c_name, t.name as t_name
from sys.key_constraints c
join sys.tables t on t.object_id = c.parent_object_id
If any constraint found on your table, remove it.
If you are receiving this error and you need to truncate the table then alternative solution could be that you can drop and re-create the table along with primary/other_keys/indexes/triggers. Please make sure that you don't need to the data in that table.
This soulution is working like a charm for me and hardly took a minute to finish. I am doing it for masking purpose.
Not for SQL Server but MySQL only.
Instead of deleting or recreating the constraint, I prefer this simpler way.
Disable the constraint validation by executing the following query first :
SET FOREIGN_KEY_CHECKS=0;
Then truncate your tables
And finally, reactivate the constraint validation :
SET FOREIGN_KEY_CHECKS=1;
Thats a common solution when you migrate databases, so you don't have to worry about the order the tables are inserted in.

How do I use cascade delete with SQL Server?

I have 2 tables: T1 and T2, they are existing tables with data. We have a one to many relationship between T1 and T2. How do I alter the table definitions to perform cascading delete in SQL Server when a record from T1 is deleted, all associated records in T2 also deleted.
The foreign constraint is in place between them. I don't want to drop the tables or create a trigger to do the deletion for T2. For example, when I delete an employee, all the review record should be gone, too.
T1 - Employee,
Employee ID
Name
Status
T2 - Performance Reviews,
Employee ID - 2009 Review
Employee ID - 2010 Review
To add "Cascade delete" to an existing foreign key in SQL Server Management Studio:
First, select your Foreign Key, and open it's "DROP and Create To.." in a new Query window.
Then, just add ON DELETE CASCADE to the ADD CONSTRAINT command:
And hit the "Execute" button to run this query.
By the way, to get a list of your Foreign Keys, and see which ones have "Cascade delete" turned on, you can run this script:
SELECT
OBJECT_NAME(f.parent_object_id) AS 'Table name',
COL_NAME(fc.parent_object_id,fc.parent_column_id) AS 'Field name',
delete_referential_action_desc AS 'On Delete'
FROM sys.foreign_keys AS f,
sys.foreign_key_columns AS fc,
sys.tables t
WHERE f.OBJECT_ID = fc.constraint_object_id
AND t.OBJECT_ID = fc.referenced_object_id
ORDER BY 1
And if you ever find that you can't DROP a particular table due to a Foreign Key constraint, but you can't work out which FK is causing the problem, then you can run this command:
sp_help 'TableName'
The SQL in that article lists all FKs which reference a particular table.
Hope all this helps.
Apologies for the long finger. I was just trying to make a point.
You will need to,
Drop the existing foreign key constraint,
Add a new one with the ON DELETE CASCADE setting enabled.
Something like:
ALTER TABLE dbo.T2
DROP CONSTRAINT FK_T1_T2 -- or whatever it's called
ALTER TABLE dbo.T2
ADD CONSTRAINT FK_T1_T2_Cascade
FOREIGN KEY (EmployeeID) REFERENCES dbo.T1(EmployeeID) ON DELETE CASCADE
You can do this with SQL Server Management Studio.
→ Right click the table design and go to Relationships and choose the foreign key on the left-side pane and in the right-side pane, expand the menu "INSERT and UPDATE specification" and select "Cascade" as Delete Rule.
Use something like
ALTER TABLE T2
ADD CONSTRAINT fk_employee
FOREIGN KEY (employeeID)
REFERENCES T1 (employeeID)
ON DELETE CASCADE;
Fill in the correct column names and you should be set. As mark_s correctly stated, if you have already a foreign key constraint in place, you maybe need to delete the old one first and then create the new one.
ON DELETE CASCADE
It specifies that the child data is deleted when the parent data is deleted.
CREATE TABLE products
( product_id INT PRIMARY KEY,
product_name VARCHAR(50) NOT NULL,
category VARCHAR(25)
);
CREATE TABLE inventory
( inventory_id INT PRIMARY KEY,
product_id INT NOT NULL,
quantity INT,
min_level INT,
max_level INT,
CONSTRAINT fk_inv_product_id
FOREIGN KEY (product_id)
REFERENCES products (product_id)
ON DELETE CASCADE
);
For this foreign key, we have specified the ON DELETE CASCADE clause which tells SQL Server to delete the corresponding records in the child table when the data in the parent table is deleted. So in this example, if a product_id value is deleted from the products table, the corresponding records in the inventory table that use this product_id will also be deleted.
First To Enable ONCascade property:
1.Drop the existing foreign key constraint
2.add a new one with the ON DELETE CASCADE setting enabled
Ex:
IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
BEGIN
ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]
ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request] FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END
ELSE
BEGIN
ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request] FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END
Second To Disable ONCascade property:
1.Drop the existing foreign key constraint
2.Add a new one with the ON DELETE NO ACTION setting enabled
Ex:
IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
BEGIN
ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]
ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request] FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END
ELSE
BEGIN
ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request] FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE NO ACTION
END
If the one to many relationship is from T1 to T2 then it doesn't represent a function and therefore cannot be used to deduce or infer an inverse function that guarantees the resulting T2 value doesn't omit tuples of T1 join T2 that are deductively valid, because there is no deductively valid inverse function. ( representing functions was the purpose of primary keys. ) The answer in SQL think is yes you can do it. The answer in relational think is no you can't do it. See points of ambiguity in Codd 1970. The relationship would have to be many-to-one from T1 to T2.
I think you cannot just delete the tables property what if this is actual production data, just delete the contents that dont affect the table schema.

Resources