SQL Server : drop multiple unknown constraints from the same table - sql

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.

Related

How is it possible to drop primary key in one step?

I would like to drop the primary key for a table, but keep the column (I know the name of the column, if it helps).
I use this script to get the name of the primary key:
-- Return the name of primary key.
SELECT key_name
FROM sys.key_constraints
WHERE type = 'PK' AND OBJECT_NAME(parent_object_id) = 'my_table';
Then I remove the key like this:
ALTER TABLE Production.TransactionHistoryArchive
DROP CONSTRAINT key_name ;
It works, but I have to run this script in one go. How it is possible to combine drop constraint with a select query?
Will throw this out there in case it's useful to you. Using Dynamic SQL you can build something that you could easily create a procedure for.
declare #Schema nvarchar(20)=N'Production',
#Table nvarchar(50)=N'TransactionHistoryArchive',
#sql nvarchar(100)=''
select #sql='ALTER TABLE '
+ QuoteName(#Schema) + '.'
+ QuoteName(#Table)
+ ' DROP CONSTRAINT '
+ QuoteName(name)
from sys.key_constraints
where type = 'PK' and Object_Name(parent_object_id) = #Table and [schema_id]=Schema_Id(#Schema)
print #sql
exec sp_executesql #sql

How can we find the name of the constraint from the Database.?

I have table prsl which have auto generated name of the constraint. I want to search where the Database kept these name.
ALTER TABLE [dbo].[PRSL] DROP CONSTRAINT [PK__PRSL__1C1D47DC0BF1ACC7]
Actually, i want to drop these constraints dynamically.
For Example
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[PRSL]')
drop all the constraint which are on a table.
Drop constraint 'when found'
If you're willing to display all constraints of a given table
select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS
where TABLE_NAME = 'YOUR TABLE NAME'
If you want to drop all constraints of the given table use this:
DECLARE #database nvarchar(50)
DECLARE #table nvarchar(50)
set #database = 'dotnetnuke'
set #table = 'tabs'
DECLARE #sql nvarchar(255)
WHILE EXISTS(select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where constraint_catalog = #database and table_name = #table)
BEGIN
select #sql = 'ALTER TABLE ' + #table + ' DROP CONSTRAINT ' + CONSTRAINT_NAME
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS
where constraint_catalog = #database and
table_name = #table
exec sp_executesql #sql
END
It worked for me...Hope it helps...

SQL Server: drop table cascade equivalent?

In oracle, to drop all tables and constraints you would type something like
DROP TABLE myTable CASCADE CONSTRAINTS PURGE;
and this would completely delete the tables and their dependencies. What's the SQL server equivalent??
In SQL Server Management Studio, go to Options / SQL Server Object Explorer / Scripting, and enable 'Generate script for dependent objects'. Then right click the table, script > drop to > new query window and it will generate it for you.
I don't believe SQL has a similarly elegant solution. You have to drop any related constraints first before you can drop the table.
Fortunately, this is all stored in the information schema and you can access that to get your whack list.
This blog post should be able to get you what you need:
http://weblogs.asp.net/jgalloway/archive/2006/04/12/442616.aspx
-- t-sql scriptlet to drop all constraints on a table
DECLARE #database nvarchar(50)
DECLARE #table nvarchar(50)
set #database = 'DatabaseName'
set #table = 'TableName'
DECLARE #sql nvarchar(255)
WHILE EXISTS(select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where constraint_catalog = #database and table_name = #table)
BEGIN
select #sql = 'ALTER TABLE ' + #table + ' DROP CONSTRAINT ' + CONSTRAINT_NAME
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS
where constraint_catalog = #database and
table_name = #table
exec sp_executesql #sql
END
This might be a horrible solution, but I find it's quick. It is similar to Vinnie's answer, but the product of the SQL statement is another series of SQL statements that will delete all constraints and tables.
(
select
'ALTER TABLE ' + tc.table_name + ' DROP CONSTRAINT ' + tc.constraint_name + ';'
from
INFORMATION_SCHEMA.TABLES t
,INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
where
t.table_name = tc.table_name
and tc.constraint_name not like '%_pk'
and tc.constraint_name not like 'pk_%'
and t.table_catalog='<schema>'
) UNION (
select
'DROP TABLE ' + t.table_name + ';'
from
INFORMATION_SCHEMA.TABLES t
where
t.table_catalog='<schema>'
)
This is all fun and games until some table references your table...
Then I must alter the code provided like so :
CREATE PROCEDURE _cascadeConstraints #database nvarchar(30) = NULL, #table nvarchar(60) = NULL
as
DECLARE #sql nvarchar(255)
WHILE EXISTS(select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where constraint_catalog = #database and table_name = #table)
BEGIN
select #sql = 'ALTER TABLE ' + #table + ' DROP CONSTRAINT ' + CONSTRAINT_NAME
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS
where constraint_catalog = #database and
table_name = #table
select #sql = 'ALTER TABLE ' + tc.TABLE_NAME + ' DROP CONSTRAINT ' + tc.CONSTRAINT_NAME
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc join
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc on
(rc.CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG and
rc.CONSTRAINT_NAME = tc.CONSTRAINT_NAME) join
INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc_pk on
(tc_pk.CONSTRAINT_CATALOG = rc.CONSTRAINT_CATALOG and
tc_pk.CONSTRAINT_NAME = rc.UNIQUE_CONSTRAINT_NAME)
where tc.constraint_catalog = #database
and tc_pk.TABLE_NAME = #table
exec sp_executesql #sql
END
go
Ultimately we are deleting our table.
So we can simply run 2 following command:
ALTER TABLE ... DROP CONSTRAINT ...
DROP TABLE ...
1> ALTER TABLE PRJ_DETAILS DROP CONSTRAINT FK_PRJ_TYPE;
-- Table name and Constraint Name are the parameter
2> DROP TABLE .
First drop constraint with its name associated with it table
Second you can drop table.
It worked for me and its easy also.
I just need delete the foreign key
DECLARE #database nvarchar(50)
DECLARE #TABLE_NAME nvarchar(250)
DECLARE #CONSTRAINT_NAME nvarchar(250)
DECLARE #sql nvarchar(350)
set #database = 'XXX'
DECLARE db_cursor CURSOR FOR
select TABLE_NAME, CONSTRAINT_NAME from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where constraint_catalog = #database and CONSTRAINT_TYPE='FOREIGN KEY'
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #TABLE_NAME, #CONSTRAINT_NAME
WHILE ##FETCH_STATUS = 0
BEGIN
select #sql = 'ALTER TABLE ' + #TABLE_NAME + ' DROP CONSTRAINT ' + #CONSTRAINT_NAME
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS
where constraint_catalog = #database and
table_name = #TABLE_NAME
exec sp_executesql #sql
FETCH NEXT FROM db_cursor INTO #TABLE_NAME, #CONSTRAINT_NAME
END
CLOSE db_cursor
DEALLOCATE db_cursor

Drop column and all dependent objects using data definition language

I need to remove a column from a table, but when I try to remove it:
The object 'object_name' is dependent
on column 'column_name'.
ALTER TABLE DROP COLUMN column_name failed because
one or more objects access this
column.
I can look for the dependency in the system tables and remove it manually, but I need to do a migration (using SQL DDL) so all others members of the team just do the update, run the migration and donĀ“t have to mess up up system objects.
Try this code:
Declare #TABLENAME varchar(max), #COLUMN varchar(max)
SET #TABLENAME = 'YOURTableName'
SET #COLUMN = 'YOURColumnName'
Declare #CONSTRAINT varchar(max)
set #CONSTRAINT ='ALTER TABLE '+#TABLENAME+' DROP CONSTRAINT '
set #CONSTRAINT = #CONSTRAINT + (select SYS_OBJ.name as CONSTRAINT_NAME
from sysobjects SYS_OBJ
join syscomments SYS_COM on SYS_OBJ.id = SYS_COM.id
join sysobjects SYS_OBJx on SYS_OBJ.parent_obj = SYS_OBJx.id
join sysconstraints SYS_CON on SYS_OBJ.id = SYS_CON.constid
join syscolumns SYS_COL on SYS_OBJx.id = SYS_COL.id
and SYS_CON.colid = SYS_COL.colid
where
SYS_OBJ.uid = user_id() and SYS_OBJ.xtype = 'D'
and SYS_OBJx.name=#TABLENAME and SYS_COL.name=#COLUMN)
exec(#CONSTRAINT)
and then run your regular alter table:
ALTER TABLE YOURTABLENAME
DROP COLUMN YOURCOLUMNNAME
With the first code you remove all the dependencies on that column and then you can remove it without problems.
EDIT - Removing Default Values Constraints:
The code above does not seems to remove DEFAULT_CONSTRAINTS so, in that case you must also use:
DECLARE #ConstraintName nvarchar(200)
SELECT #ConstraintName = Name FROM SYS.DEFAULT_CONSTRAINTS WHERE PARENT_OBJECT_ID = OBJECT_ID('__TableName__') AND PARENT_COLUMN_ID = (SELECT column_id FROM sys.columns WHERE NAME = N'__ColumnName__' AND object_id = OBJECT_ID(N'__TableName__'))
IF #ConstraintName IS NOT NULL
EXEC('ALTER TABLE __TableName__ DROP CONSTRAINT ' + #ConstraintName)

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;