How to drop all foreign keys from a SQL Server database? - sql

I want to drop the all foreign keys that have the following conditions.
SELECT CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE TABLE_NAME IN ('Table1', 'Table2')
AND CONSTRAINT_NAME LIKE '%FK__%__DL%'

There is a table named INFORMATION_SCHEMA.TABLE_CONSTRAINTS which stores all tables constraints. constraint type of FOREIGN KEY is also keeps in that table. So by filtering of this type you can reach to all foreign keys.
SELECT *
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'
If you create a dynamic query (for DROP-ing the foreign key) in order to alter the table, you can reach to the aim of altering the constraints of all tables.
WHILE(EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'FOREIGN KEY' AND TABLE_NAME IN ('Table1', 'Table2') AND CONSTRAINT_NAME LIKE '%FK__%__DL%'))
BEGIN
DECLARE #sql_alterTable_fk NVARCHAR(2000)
SELECT TOP 1 #sql_alterTable_fk = ('ALTER TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME + '] DROP CONSTRAINT [' + CONSTRAINT_NAME + ']')
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'
AND TABLE_NAME IN ('Table1', 'Table2')
AND CONSTRAINT_NAME LIKE '%FK__%__DL%'
EXEC (#sql_alterTable_fk)
END
EXISTS function with its parameter assures that there is at least one constrain for foreign key.

Similar to what Siyavash suggested, but I prefer a bit more control over the process..
If you use this query:
SELECT CONCAT('ALTER TABLE ', TABLE_SCHEMA, '.[', TABLE_NAME, '] DROP CONSTRAINT [', CONSTRAINT_NAME, ']')
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'
Run it; it generates a list of drop commands for every FK in the DB. You can then either pick out the ones you want to execute or you can add more clauses the the WHERE to restrict further
As with all "SQL that writes SQL" you run it by copying the results out of the grid, pasting into a new window in SSMS and running them (F5)
Hence, your query, with the CONCAT that writes the drop command:
SELECT CONCAT('ALTER TABLE ', TABLE_SCHEMA, '.[', TABLE_NAME, '] DROP CONSTRAINT [', CONSTRAINT_NAME, ']')
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE TABLE_NAME IN ('Table1', 'Table2')
AND CONSTRAINT_NAME LIKE '%FK__%__DL%'

Related

SQL Server : drop multiple unknown constraints from the same table

I checked the answer given in this SO question , to drop constraints whose names are not known.
In SQL Server, can we assume they will always be in the same format given? (FK__TABLENAME__KEYPREFIX)?
What does T(c) define?
If two such constraints need to be dropped from the same table, is the following correct?
DECLARE #sql1 NVARCHAR(MAX);
DECLARE #sql2 NVARCHAR(MAX);
SELECT
#sql1 = c
FROM
(SELECT
'ALTER TABLE DOC_INVS_1 DROP CONSTRAINT ' + CONSTRAINT_NAME + '; '
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE
TABLE_NAME = 'DOC_INVS_1'
AND CONSTRAINT_NAME LIKE 'FK__DOC_INVS___kntr%') T(c);
SELECT
#sql2 = c
FROM
(SELECT
'ALTER TABLE DOC_INVS_1 DROP CONSTRAINT ' + CONSTRAINT_NAME + '; '
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE
TABLE_NAME = 'DOC_INVS_1'
AND CONSTRAINT_NAME LIKE 'FK__DOC_INVS___aaaa%') T(c);
EXEC(#sql1);
EXEC(#sql2);
Note
The actual end goal is to add a 'CASCADE ON DELETE' to a foreign key, which had been added to the wrong key. I learned that you can't just add the cascade option by altering, so the approach is to drop both and then create again.

Find all tables in database By primaryKey

I'm searching for a query that can retrieve all the tables by the specified key/keys name on a specific database.
Something like this:
SELECT table_name
FROM information_Schema.columns
WHERE column_name='ID_UNICO'
AND Constraint_Type = 'PRIMARY KEY'
I've been searching and the best I could find was:
SELECT Col.Column_Name from
INFORMATION_SCHEMA.TABLE_CONSTRAINTS Tab,
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE Col
WHERE
Col.Constraint_Name = Tab.Constraint_Name
AND Col.Table_Name = Tab.Table_Name
AND Constraint_Type = 'PRIMARY KEY'
AND Col.Table_Name = '<your table name>'
this retrieves the PK's of a specific table, I want to find table_name BY PK name.
SELECT table_name
FROM information_Schema.columns
WHERE column_name='ID_UNICO'
and ordinal_position = 1;
also found this but this gives me the first column of the table, which doesn't ensure me that it it the PK.
Couldn't find any duplicate either.
Would this work for you?
DECLARE #ColName AS VARCHAR(MAX)
SET #ColName = 'CourseId'
SELECT
TABLE_NAME
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
AND COLUMN_NAME = #ColName
You can use this query. Replace 'YOUR_COLUMN_NAME' with your primary key column name.
SELECT Table_Name
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + QUOTENAME(CONSTRAINT_NAME)), 'IsPrimaryKey') = 1
and COLUMN_NAME ='YOUR_COLUMN_NAME'
Here you go, join TABLE_CONSTRAINTS to CONSTRAINT_COLUMN_USAGE to tie the constraint name to the column then return your TABLE_NAME:
SELECT CCU.COLUMN_NAME,
CONS.TABLE_NAME
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE CCU
JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS CONS
ON CONS.CONSTRAINT_NAME = CCU.CONSTRAINT_NAME
WHERE CONS.CONSTRAINT_TYPE = 'PRIMARY KEY'
AND CCU.COLUMN_NAME = 'ID_UNICO'

How to drop all tables from a database in sql server 2005 in a statement except one table

I am using sql-server 2005. Initially, for learning purpose I created many tables now I want to drop all those tables except one which is currently I am working on.
Is there any code or query with which I can drop all tables from my that database except that one useful table.
One way I think is to copy that table into new database using SELECT INTO... clause and drop that database but don't know is this a good way to solve this problem.
If the tables aren't very big I'd probably just select them all in the "Object Explorer Details" window in SSMS then hit delete.
For a programmatic solution you could use
EXEC sys.sp_MSforeachtable
N'IF OBJECT_ID(''?'') <> OBJECT_ID(''dbo.YourTableToKeep'')
DROP TABLE ?
'
Both methods might need repeated runs in order to delete all tables involved in FK relationships (a table cannot be deleted if another table has an FK referencing it).
You can use sql to create all drops staments that you needs. For example the next sql query
USE [MyDatabase];
GO
SELECT
replace(
replace('DROP TABLE [{Schema}].[{TableName}];'
,'{Schema}',TABLE_SCHEMA)
,'{TableName}',TABLE_NAME)
FROM
INFORMATION_SCHEMA.TABLES
WHERE
TABLE_NAME NOT IN ('TableNameOne','TableNameTwo')
and get the result executing the query.
Copy first column of the query and paste it in a new query window.
It's easy to see, that you get a list of drop staments for all tables except 'TableNameOne' and 'TableNameTwo',...
Im think that is very simple...
/* Drop all Foreign Key constraints */
DECLARE #name VARCHAR(128)
DECLARE #constraint VARCHAR(254)
DECLARE #SQL VARCHAR(254)
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY TABLE_NAME)
WHILE #name is not null
BEGIN
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
WHILE #constraint IS NOT NULL
BEGIN
SELECT #SQL = 'ALTER TABLE [dbo].[' + RTRIM(#name) +'] DROP CONSTRAINT [' + RTRIM(#constraint) +']'
EXEC (#SQL)
PRINT 'Dropped FK Constraint: ' + #constraint + ' on ' + #name
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND CONSTRAINT_NAME <> #constraint AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
END
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY TABLE_NAME)
END
GO
/* Drop all Primary Key constraints */
DECLARE #name VARCHAR(128)
DECLARE #constraint VARCHAR(254)
DECLARE #SQL VARCHAR(254)
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY TABLE_NAME)
WHILE #name IS NOT NULL
BEGIN
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
WHILE #constraint is not null
BEGIN
SELECT #SQL = 'ALTER TABLE [dbo].[' + RTRIM(#name) +'] DROP CONSTRAINT [' + RTRIM(#constraint)+']'
EXEC (#SQL)
PRINT 'Dropped PK Constraint: ' + #constraint + ' on ' + #name
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND CONSTRAINT_NAME <> #constraint AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
END
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY TABLE_NAME)
END
GO
/* Drop all tables */
DECLARE #name VARCHAR(128)
DECLARE #SQL VARCHAR(254)
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 ORDER BY [name])
WHILE #name IS NOT NULL
BEGIN
SELECT #SQL = 'DROP TABLE [dbo].[' + RTRIM(#name) +']'
EXEC (#SQL)
PRINT 'Dropped Table: ' + #name
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 AND [name] > #name ORDER BY [name])
END
GO

Modify table: How to change 'Allow Nulls' attribute from not null to allow null

How to change one attribute in a table using T-SQL to allow nulls (not null --> null)? Alter table maybe?
-- replace NVARCHAR(42) with the actual type of your column
ALTER TABLE your_table
ALTER COLUMN your_column NVARCHAR(42) NULL
Yes you can use ALTER TABLE as follows:
ALTER TABLE [table name] ALTER COLUMN [column name] [data type] NULL
Quoting from the ALTER TABLE documentation:
NULL can be specified in ALTER COLUMN to force a NOT NULL column to allow null values, except for columns in PRIMARY KEY constraints.
ALTER TABLE is right:
ALTER TABLE MyCustomers ALTER COLUMN CompanyName VARCHAR(20) NULL
For MySQL, MariaDB
ALTER TABLE [table name] MODIFY COLUMN [column name] [data type] NULL
Use MODIFY COLUMN instead of ALTER COLUMN.
ALTER TABLE public.contract_termination_requests
ALTER COLUMN management_company_id DROP NOT NULL;
I wrote this so I could edit all tables and columns to null at once:
select
case
when sc.max_length = '-1' and st.name in ('char','decimal','nvarchar','varchar')
then
'alter table [' + so.name + '] alter column [' + sc.name + '] ' + st.name + '(MAX) NULL'
when st.name in ('char','decimal','nvarchar','varchar')
then
'alter table [' + so.name + '] alter column [' + sc.name + '] ' + st.name + '(' + cast(sc.max_length as varchar(4)) + ') NULL'
else
'alter table [' + so.name + '] alter column [' + sc.name + '] ' + st.name + ' NULL'
end as query
from sys.columns sc
inner join sys.types st on st.system_type_id = sc.system_type_id
inner join sys.objects so on so.object_id = sc.object_id
where so.type = 'U'
and st.name <> 'timestamp'
order by st.name
This is the approach to do this: -
Check whether the table or column exists or not.
If yes, then alter the column. e.g:-
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_CATALOG = 'DBName' AND
TABLE_SCHEMA = 'SchemaName' AND
TABLE_NAME = 'TableName' AND
COLUMN_NAME = 'ColumnName')
BEGIN
ALTER TABLE DBName.SchemaName.TableName ALTER COLUMN ColumnName [data type] NULL
END
If you don't have any schema then delete the schema line because you don't need to give the default schema.
So the simplest way is,
alter table table_name change column_name column_name int(11) NULL;

How to drop a list of SQL Server tables, ignoring constraints?

I have a list of half a dozen MSSQL 2008 tables that I would like to remove at once from my database. The data has been entirely migrated to new tables. There is no reference in the new tables to the old tables.
The problem being that old tables comes with loads of inner FK constraints that have been autogenerated by a tool (aspnet_regsql actually). Hence dropping manually all constraints is a real pain.
How can I can drop the old tables ignoring all inner constraints?
It depends on how you want to drop the tables. If list of tables need to drop covers almost above 20 % of tables under your DB.
Then I will disable all the constraints in that DB under my script and drop the tables and Enable the constraints under the same script.
--To Disable a Constraint at DB level
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
--Write the code to DROP tables
DROP TABLE TABLENAME
DROP TABLE TABLENAME
DROP TABLE TABLENAME
--To Enable a Constraint at DB level
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
Finally to check the Status of your constraints fire up this Query.
--Checks the Status of Constraints
SELECT (CASE
WHEN OBJECTPROPERTY(CONSTID, 'CNSTISDISABLED') = 0 THEN 'ENABLED'
ELSE 'DISABLED'
END) AS STATUS,
OBJECT_NAME(CONSTID) AS CONSTRAINT_NAME,
OBJECT_NAME(FKEYID) AS TABLE_NAME,
COL_NAME(FKEYID, FKEY) AS COLUMN_NAME,
OBJECT_NAME(RKEYID) AS REFERENCED_TABLE_NAME,
COL_NAME(RKEYID, RKEY) AS REFERENCED_COLUMN_NAME
FROM SYSFOREIGNKEYS
ORDER BY TABLE_NAME, CONSTRAINT_NAME,REFERENCED_TABLE_NAME, KEYNO
If you dont want to disable the constraints at Database level then make a list of tables which you want to drop.
Step1 : Check the Constraints associated with thos tables
SELECT *
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('dbo.Tablename')
Step2 : Disable the Constraints which are associated with these tables.
ALTER TABLE MyTable NOCHECK CONSTRAINT MyConstraint
Step3 : Drop the tables
DROP TABLE TABLENAME
A simple DROP TABLE dbo.MyTable will ignore all constraints (and triggers) except foreign keys (unless you drop the child/referencing table first) where you may have to drop these first.
Edit: after comment:
There is no automatic way. You'll have to iterate through sys.foreign_keys and generate some ALTER TABLE statements.
Run the following script to delete all the constraints in all tables under current DB and then run the drop table statements.
DECLARE #dropAllConstraints NVARCHAR(MAX) = N'';
SELECT #dropAllConstraints += N'
ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id))
+ '.' + QUOTENAME(OBJECT_NAME(parent_object_id)) +
' DROP CONSTRAINT ' + QUOTENAME(name) + ';'
FROM sys.foreign_keys;
EXEC sp_executesql #dropAllConstraints
I found a reasonable(ish) way to do it by making SQL write the SQL to drop the constraints:
select concat("alter table ", table_name, " drop ", constraint_type ," ", constraint_name, ";")
from information_schema.table_constraints
where table_name like 'somefoo_%'
and
constraint_type <> "PRIMARY KEY";
You will want to modify the table name to suit your needs, or possibly select against other column/values.
Also, this would select any non primary key constraint, which might be too big of a sledgehammer. Maybe you need to just set it to =?
I am not a DBA. there may be better ways to do this, but it worked well enough for my purposes.
I finally found the solution based on the script provided by Jason Presley. This script automatically removes all constraints in the DB. It's easy to add a WHERE clause so that it only applies to the set of concerned tables. After that, dropping all tables is a straightforward.
Be very careful with the following script, all tables, views, functions, stored procedures and user defined types from a database ignoring all constraints.
/*
Description: This script will remove all tables, views, functions, stored procedures and user defined types from a database.
*/
declare #n char(1)
set #n = char(10)
declare #stmt nvarchar(max)
-- procedures
select #stmt = isnull( #stmt + #n, '' ) +
'drop procedure [' + schema_name(schema_id) + '].[' + name + ']'
from sys.procedures
-- check constraints
select #stmt = isnull( #stmt + #n, '' ) +
'alter table [' + schema_name(schema_id) + '].[' + object_name( parent_object_id ) + '] drop constraint [' + name + ']'
from sys.check_constraints
-- functions
select #stmt = isnull( #stmt + #n, '' ) +
'drop function [' + schema_name(schema_id) + '].[' + name + ']'
from sys.objects
where type in ( 'FN', 'IF', 'TF' )
-- views
select #stmt = isnull( #stmt + #n, '' ) +
'drop view [' + schema_name(schema_id) + '].[' + name + ']'
from sys.views
-- foreign keys
select #stmt = isnull( #stmt + #n, '' ) +
'alter table [' + schema_name(schema_id) + '].[' + object_name( parent_object_id ) + '] drop constraint [' + name + ']'
from sys.foreign_keys
-- tables
select #stmt = isnull( #stmt + #n, '' ) +
'drop table [' + schema_name(schema_id) + '].[' + name + ']'
from sys.tables
-- user defined types
select #stmt = isnull( #stmt + #n, '' ) +
'drop type [' + schema_name(schema_id) + '].[' + name + ']'
from sys.types
where is_user_defined = 1
exec sp_executesql #stmt
I suspect that you would have to do an 'alter' command on the offending tables before the drop to remove the forigen key contraints.
ALTER TABLE Orders DROP FOREIGN KEY fk_PerOrders;
DROP TABLE Orders;
Of course if you drop the child tables first, then you wont have this problem.
(unless you have table A contraint to table B and table B constraint to A, then you will need to Alter one of the tables, e.g. A to remove the constraint)
e.g. this WONT work, since Orders has a contraint from Order_Lines
DROP TABLE Orders;
DROP TABLE Order_lines;
e.g. this will work
DROP TABLE Order_lines;
DROP TABLE Orders;