How to remove foreign key constraint in sql server? - sql-server

I want to remove foreign key from another table so i can insert values of my choice.
I am new in databases so please tell me correct sql query to drop or remove foreign key value.

Try following
ALTER TABLE <TABLE_NAME> DROP CONSTRAINT <FOREIGN_KEY_NAME>
Refer : http://www.w3schools.com/sql/sql_foreignkey.asp

Its wrong to do that in refer to referential integrity, because once its broken its not easy to turn it on again without having to go through the records and delete the ones which breaks the constraints.
Anyway the Syntax is as follows:
ALTER TABLE Tablename DROP CONSTRAINT ContName;
See MSDN:
Delete Primary Keys
Delete Foreign Key Relationships

ALTER TABLE [TableName] DROP CONSTRAINT [CONSTRAINT_NAME]
But, be careful man, once you do that, you may never get a chance back, and you should read some basic database book see why we need foreign key

To remove all the constraints from the DB:
SELECT 'ALTER TABLE ' + Table_Name +' DROP CONSTRAINT ' + Constraint_Name
FROM Information_Schema.CONSTRAINT_TABLE_USAGE

You should consider (temporarily) disabling the constraint before you completely delete it.
If you look at the table creation TSQL you will see something like:
ALTER TABLE [dbo].[dbAccounting] CHECK CONSTRAINT [FK_some_FK_constraint]
You can run
ALTER TABLE [dbo].[dbAccounting] NOCHECK CONSTRAINT [FK_some_FK_constraint]
... then insert/update a bunch of values that violate the constraint, and then turn it back on by running the original CHECK statement.
(I have had to do this to cleanup poorly designed systems I've inherited in the past.)

Drop all the foreign keys of a table:
USE [Database_Name]
DECLARE #FOREIGN_KEY_NAME VARCHAR(100)
DECLARE FOREIGN_KEY_CURSOR CURSOR FOR
SELECT name FOREIGN_KEY_NAME FROM sys.foreign_keys WHERE parent_object_id = (SELECT object_id FROM sys.objects WHERE name = 'Table_Name' AND TYPE = 'U')
OPEN FOREIGN_KEY_CURSOR
----------------------------------------------------------
FETCH NEXT FROM FOREIGN_KEY_CURSOR INTO #FOREIGN_KEY_NAME
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #DROP_COMMAND NVARCHAR(150) = 'ALTER TABLE Table_Name DROP CONSTRAINT' + ' ' + #FOREIGN_KEY_NAME
EXECUTE Sp_executesql #DROP_COMMAND
FETCH NEXT FROM FOREIGN_KEY_CURSOR INTO #FOREIGN_KEY_NAME
END
-----------------------------------------------------------------------------------------------------------------
CLOSE FOREIGN_KEY_CURSOR
DEALLOCATE FOREIGN_KEY_CURSOR

Depending on the DB you are using there's a syntax or another.
If you're using Oracle you have to put what the other users told you:
ALTER TABLE table_name DROP CONSTRAINT fk_name;
But if you use MySQL then this will give you a syntax error, instead you can type:
ALTER TABLE table_name DROP INDEX fk_name;

firstly use
show create table table_name;
to see the descriptive structure of your table.
There you may see constraints respective to foreign keys you used in that table.
First delete the respective constraint with
alter table table_name drop constraint constraint_name;
and then delete the respective foreign keys or column you wanted...GoodLuck!!

ALTER TABLE table
DROP FOREIGN KEY fk_key
EDIT: didn't notice you were using sql-server, my bad
ALTER TABLE table
DROP CONSTRAINT fk_key

Use those queries to find all FKs:
Declare #SchemaName VarChar(200) = 'Schema Name'
Declare #TableName VarChar(200) = 'Table name'
-- Find FK in This table.
SELECT
'IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N''' +
'[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' + FK.name + ']'
+ ''') AND parent_object_id = OBJECT_ID(N''' +
'[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].['
+ OBJECT_NAME(FK.parent_object_id) + ']' + ''')) ' +
'ALTER TABLE ' + OBJECT_SCHEMA_NAME(FK.parent_object_id) +
'.[' + OBJECT_NAME(FK.parent_object_id) +
'] DROP CONSTRAINT ' + FK.name
, S.name , O.name, OBJECT_NAME(FK.parent_object_id)
FROM sys.foreign_keys AS FK
INNER JOIN Sys.objects As O
ON (O.object_id = FK.parent_object_id )
INNER JOIN SYS.schemas AS S
ON (O.schema_id = S.schema_id)
WHERE
O.name = #TableName
And S.name = #SchemaName
-- Find the FKs in the tables in which this table is used
SELECT
' IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N''' +
'[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' + FK.name + ']'
+ ''') AND parent_object_id = OBJECT_ID(N''' +
'[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].['
+ OBJECT_NAME(FK.parent_object_id) + ']' + ''')) ' +
' ALTER TABLE ' + OBJECT_SCHEMA_NAME(FK.parent_object_id) +
'.[' + OBJECT_NAME(FK.parent_object_id) +
'] DROP CONSTRAINT ' + FK.name
, S.name , O.name, OBJECT_NAME(FK.parent_object_id)
FROM sys.foreign_keys AS FK
INNER JOIN Sys.objects As O
ON (O.object_id = FK.referenced_object_id )
INNER JOIN SYS.schemas AS S
ON (O.schema_id = S.schema_id)
WHERE
O.name = #TableName
And S.name = #SchemaName

Alternatively, you can also delete a Foreign Key Constraint from the SQL Server Management Studio itself. You can try it if the commands do not work.
Expand your database view.
Right Click on Table which has foreign key constraint. Choose Design. A tab with the information about table columns will open.
Right click on the column which has the foreign key reference. Or you can right click on any column. Choose Relationships.
A list of relationships will appear (if you have one) in a pop up window.
From there you can delete the foreign key constraint.
I hope that helps

If you find yourself in a situation where the FK name of a table has been auto-generated and you aren't able to view what it exactly is (in the case of not having rights to a database for instance) you could try something like this:
DECLARE #table NVARCHAR(512), #sql NVARCHAR(MAX);
SELECT #table = N'dbo.Table';
SELECT #sql = 'ALTER TABLE ' + #table
+ ' DROP CONSTRAINT ' + NAME + ';'
FROM sys.foreign_keys
WHERE [type] = 'F'
AND [parent_object_id] = OBJECT_ID(#table);
EXEC sp_executeSQL #sql;
Build up a stored proc which drops the constraint of the specified table without specifying the actual FK name. It drops the constraint where the object [type] is equal to F (Foreign Key constraint).
Note: if there are multiple FK's in the table it will drop them all. So this solution works best if the table you are targeting has just one FK.

If you don't know foreign key constraint name then try this to find it.
sp_help 'TableName'
additionally for different schema
sp_help 'schemaName.TableName'
then
ALTER TABLE <TABLE_NAME> DROP CONSTRAINT <FOREIGN_KEY_NAME>

To be on the safer side, just name all your constraints and take note of them in the comment section.
ALTER TABLE[table_name]
DROP CONSTRAINT Constraint_name

alter table <referenced_table_name> drop primary key;
Foreign key constraint will be removed.

Related

How to detect if a table is a FileTable in SQL Server

I am working with an existing SQL script which drops all foreign keys from a database. This runs into trouble if one of the tables is a FileTable.
The primary question: is there a way to detect that a particular table is a FILETABLE and skip dropping the foreign keys on that table?
If that is possible: is it also possible to get even more granular and drop any non-system generated foreign keys from the FILETABLE by differentiating between system foreign keys and custom foreign keys?
DECLARE #fkdel varchar(512);
DECLARE FkCrsr CURSOR FOR
SELECT 'ALTER TABLE [' + TABLE_SCHEMA + '].[' + TABLE_NAME + '] DROP CONSTRAINT [' + CONSTRAINT_NAME +']'
FROM information_schema.table_constraints WITH (NOLOCK)
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY';
OPEN FkCrsr;
FETCH NEXT FROM FkCrsr INTO #fkdel;
WHILE ##FETCH_STATUS = 0
BEGIN;
PRINT #fkdel;
EXEC (#fkdel);
FETCH NEXT FROM FkCrsr INTO #fkdel;
END;
CLOSE FkCrsr;
DEALLOCATE FkCrsr;
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all";
Running this on a database containing a FileTable results in an error like
Msg 3865, Level 16, State 1, Line 3
The operation on object 'FK__DocumentS__paren__3A69DAC6' is blocked. The object is a FileTable system defined object and user modifications are not allowed.
Msg 3727, Level 16, State 0, Line 3
Could not drop constraint. See previous errors.
You should not be using the information schema views for this. Especially since you care about the schema. The MS documentation even states not to use this. https://learn.microsoft.com/en-us/sql/relational-databases/system-information-schema-views/table-constraints-transact-sql?view=sql-server-ver15
If you instead use the system views this becomes a lot simpler. For example sys.tables has a column "is_filetable". https://learn.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-tables-transact-sql?view=sql-server-ver15 Also notice I am using QUOTENAME here instead of manually adding square brackets.
Then you can query sys.foreign_keys to find all your foreign keys since that is the only type of constraint you are concerned with.
Your whole looping construct could be simplified to something like this.
declare #SQL nvarchar(max) = ''
select #SQL = #SQL + 'ALTER TABLE ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' DROP CONSTRAINT ' + QUOTENAME(fk.name) + ';'
from sys.foreign_keys fk
join sys.tables t on t.object_id = fk.parent_object_id
join sys.schemas s on s.schema_id = t.schema_id
where t.is_filetable = 0
select #SQL
--uncomment the line below to execute your dynamic sql
--exec sp_executesql #SQL
That takes us to sp_msforeachtable. It is rarely a good idea to use undocumented procedures like this. I would also be a bit nervous that you are turning off every constraint on every table instead of just the ones you removed. Maybe instead you should capture all the tables you are going to drop foreign keys from (before you drop them) and then disable all the constraints on ONLY those tables.

Executing script for add primary keys to all tables returns error

I want to add Primary Key IDD to every 'Temp...' table in the schema. I'm trying to do it the following way:
DECLARE #addId VARCHAR(MAX) = '';
SELECT #addId = #addId + 'ALTER TABLE ['+ TABLE_NAME +'] ADD IDD int IDENTITY(1,1);ALTER TABLE ['+TABLE_NAME +'] ADD PRIMARY KEY (IDD);' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE 'Temp%'
EXEC (#addId );
I'm returned with such error:
Multiple identity columns specified for table 'TempTable'. Only one identity column per table is allowed.
What is my wrongdoing?
EDIT: There is no Primary Key already defined in the tables.
try this
SELECT #addId = #addId +
ALTER TABLE ['+ TABLE_NAME +'] ADD IDD int PRIMARY KEY IDENTITY(1,1);
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE 'Temp%'
Use this query to get all table which doesn't have primary key:
select * FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME NOT IN(SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE='PRIMARY KEY')
And modify your dynamic query accordingly.

Sync Database when tables have Foreign Keys

One of our SQL Databases is a sync of somebody else's Database. There are about 100 tables in their database, and about 120 in ours.
In ours, we have a few additional tables that help us do mapping and track other data. As a part of our additional tables, we create Foreign Keys onto some of the DBO Tables that are Sync'd from our provider.
Therefore, a Customers table that is sync'd from our Provider now has Foreign Key constraints on a mySchema.Receipts table, which has a CustomerID field.
The Provider's Sync broke, and they said that they cannot Drop the Customers table in order to Sync the data, because it now says there is a Foriegn key against Customers.
Isn't there a way I can tell them in SQL that SQL can like... ignore Foriegn Key constraints when Sync'ing or something?
If the sync job is deleting data from the target database, you can disable constraints, and then enable them again after the sync. If your sync job is truncating tables or drop and rebuilding tables, them the foreign key constraints need to be dropped, then rebuilt again after the sync.
Using the "delete from target" approach:
If target tables are part of the "dbo" schema, your process could look like:
(1) Disable all foreign keys constrains in target database.
Example:
exec sp_MSforeachtable 'IF ''?'' like ''%[dbo]%'' ALTER TABLE ? NOCHECK CONSTRAINT ALL;'
(2) Delete all data from the target tables
(3) Copy all data from the source to the target tables, including identity column data if needed.
(4) Restore all foreign keys constrains in target database.
Example:
exec sp_MSforeachtable 'IF ''?'' like ''%[dbo]%'' ALTER TABLE ? CHECK CONSTRAINT ALL;'
** To help further automate this, take advantage of the INFORMATION_SCHEMA.TABLES view in SQL Server.
SELECT 'dbo.' + TABLE_NAME as TableName, 'SELECT * FROM dbo.['+ TABLE_NAME +'];' AS Script FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' and TABLE_NAME NOT IN (comma delimited list of tables to exclude)
If needed, the below script will query all of the foreign key constraints:
IF OBJECT_ID('tempdb..#TEMPCONS') IS NOT NULL DROP TABLE #TEMPCONS;
SELECT KCU1.TABLE_SCHEMA, KCU1.TABLE_NAME, KCU1.CONSTRAINT_NAME, KCU1.COLUMN_NAME, KCU1.ORDINAL_POSITION, RC.UPDATE_RULE, RC.DELETE_RULE,
KCU2.TABLE_NAME AS REF_TABLE_NAME, KCU2.CONSTRAINT_NAME AS REF_CONSTRAINT_NAME, KCU2.COLUMN_NAME AS REF_COLUMN_NAME, KCU2.ORDINAL_POSITION AS REF_ORDINAL_POSITION,
KCU2.TABLE_SCHEMA AS REF_TABLE_SCHEMA INTO #TEMPCONS
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC INNER JOIN
INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU1 ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG AND
KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME INNER JOIN
INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU2 ON KCU2.CONSTRAINT_CATALOG = RC.UNIQUE_CONSTRAINT_CATALOG AND
KCU2.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA AND KCU2.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME AND
KCU2.ORDINAL_POSITION = KCU1.ORDINAL_POSITION
ORDER BY TABLE_NAME, CONSTRAINT_NAME, ORDINAL_POSITION;
ALTER TABLE #TEMPCONS ADD COLUMN_LIST VARCHAR(MAX), REF_COLUMN_LIST VARCHAR(MAX);
-- Rows to column concatenation
DECLARE #COLUMN_NAME varchar(MAX), #Columns VARCHAR(MAX);
UPDATE #TEMPCONS SET #Columns = COLUMN_LIST = COALESCE(CASE COALESCE(#COLUMN_NAME, '')
WHEN CONSTRAINT_NAME THEN #Columns + ', ' + '['+ COLUMN_NAME +']' ELSE '['+ COLUMN_NAME +']' END, ''), #COLUMN_NAME = CONSTRAINT_NAME;
UPDATE #TEMPCONS SET #Columns = REF_COLUMN_LIST = COALESCE( CASE COALESCE(#COLUMN_NAME, '')
WHEN CONSTRAINT_NAME THEN #Columns + ', ' + '['+REF_COLUMN_NAME +']' ELSE '['+REF_COLUMN_NAME +']' END, ''), #COLUMN_NAME = CONSTRAINT_NAME;
SELECT TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_NAME, UPDATE_RULE, DELETE_RULE, MAX(COLUMN_LIST) AS COLUMN_LIST,
REF_TABLE_SCHEMA, REF_TABLE_NAME, REF_CONSTRAINT_NAME, MAX(REF_COLUMN_LIST) AS REF_COLUMN_LIST
FROM #TEMPCONS
GROUP BY REF_TABLE_SCHEMA, TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_NAME, UPDATE_RULE, DELETE_RULE, REF_TABLE_NAME, REF_CONSTRAINT_NAME;

SQL Server - Foreign key creation to multiple tables

I have a requirement where I need to create a foreign key for more than 200 tables. Ex, there is emp table which has ID has primary key, now the 200 tables have emp_id, which I need to reference to emp.id.
I know I can write 200 alter statements to create the foreign key. Is there an easier way to create with one simple script?
Please advise. Thanks for your help.
Here is a trick to do it
DECLARE #sql NVARCHAR(max)=''
SELECT #sql += '
ALTER TABLE ' + Object_name(object_id)
+ '
ADD CONSTRAINT FK_'
+ Object_name(object_id)
+ '_EMP_emp_id FOREIGN KEY (emp_id) REFERENCES EMP(id);'
FROM sys.COLUMNS
WHERE NAME = 'emp_id'
--Print #sql
EXEC Sp_executesql
#sql
Note :
Print #SQL variable and check the generated SQL is good
Above code consider's all the 200 table has the same name 'emp_id' to which foreign key is created
This may fail when the 'emp_id' column has bad data (ie) a 'emp_id' which is not present in EMP table
You could probably generate the alter table statements dynamically using information_schema.columns. Something like this should get you started:
SELECT 'ALTER TABLE '+ TABLE_NAME +
' ADD CONSTRAINT FK_'+ TABLE_NAME +'_Emp FOREIGN KEY ('+ COLUMN_NAME +')'+
' REFERENCES emp (Id)'+
' ON DELETE CASCADE'+
' ON UPDATE CASCADE;'+
' GO '
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = 'emp_id'

Drop foreign key without knowing the name of the constraint?

I have created one table using the below command:
create table Table1(
Id int Not Null
Foreign key
references Table2(Id)
on delete cascade
on update cascade,
UserName nvarchar(150),
TimeInSeconds int Not Null
primary key(Id,TimeInSeconds)
);
But now I want to drop the foreign key.
As I haven't given a constraint name, I can't use:
Alter table <tablename>
drop foreign key <foreign key name>
Is there any way?
You can find the name of the constraint in INFORMATION_SCHEMA.TABLE_CONSTRAINTS
select CONSTRAINT_NAME
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS
where TABLE_NAME = 'Table1'
Similar to Ed's Answer but you can use this to select the key name based on the table and column name.
That way you can run it in a script or maybe as a subquery to drop the constraint.
SELECT CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_NAME = 'post'
AND COLUMN_NAME = 'userID'
Expanding on the answers since I ran into some gotchas. Also, I had 2 foreign keys declared, so I added an optional key to keep, if it's null it'll just be ignored:
declare #name varchar(255),
#table varchar(255) = 'mytable',
#column varchar(255) = 'mykeycolumn',
#validkey varchar(255) = 'mykeyIwanttokeep'
SELECT #name = CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_NAME = #table
AND COLUMN_NAME = #column
AND (CONSTRAINT_NAME != #validkey or #validkey is null)
declare #sql varchar(1023) = 'alter table ' + #table + ' drop ' + #name
exec (#sql)
A SQL Server option:
DECLARE #foreignkey varchar(100)
DECLARE #tablename varchar(100)
DECLARE #command nvarchar(1000)
DECLARE db_cursor CURSOR FOR
SELECT fk.name, t.name
FROM sys.foreign_keys fk
JOIN sys.tables t ON t.object_id = fk.parent_object_id
WHERE t.name IN (
'table_1_name_here',
'table_2_name_here'
)
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #foreignkey, #tablename
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #command = 'ALTER TABLE ' + #tablename + ' DROP CONSTRAINT ' + #foreignkey
EXECUTE(#command)
FETCH NEXT FROM db_cursor INTO #foreignkey, #tablename
END
CLOSE db_cursor
DEALLOCATE db_cursor
The SQL selects all the constraints for the tables you care about into a cursor and drops them one by one. All you need to know are the names of the tables you want them dropped from.
To drop a foreign key use the following commands :
SHOW CREATE TABLE table_name;
ALTER TABLE table_name DROP FOREIGN KEY table_name_ibfk_3;
("table_name_ibfk_3" is constraint foreign key name assigned for unnamed constraints). It varies.
ALTER TABLE table_name DROP column_name.
If you just look at the table in enterprise manager / management studio you will be able to see the list of keys and delete it from there.
Never mind, below is Postgres syntax. It would be better if the question had sql server in the title as I didn't notice the tag
You could also drop and re-add the primary key on the parent table using cascade. This will remove any foreign keys that reference that table without you needing to know the foreign key names.
ALTER TABLE parent_table
DROP CONSTRAINT 'pk_id' CASCADE
-- add back pk
ALTER TABLE parent_table
ADD CONSTRAINT 'pk_id' PRIMARY KEY (id)
WARNING: you'd want to check all the dependencies first and if there are other tables, you'd need to add back their foreign keys. That does allow you to name the foreign keys properly when you add them back. This approach also may not be viable in a high transaction system due to the blocking transaction.
you can put:
> show create table tablename;
you will see how was created the table...columns, types...etc. and you could see your constraint name.

Resources