SQL Server column date default gatedate() to datetime in scripts - sql

Note> I can not modify old scripts!!!
First script create table TABLENAME.
I have table TABLENAME with column COLUMNNAME DATE DEFAULT GETDATE();
I need to do: ->
ALTER TABLE TABLENAME
ALTER COLUMN COLUMNNAME DATETIME;
I get a error:
The object 'DF__TABLENAME__COLUMNNAME__7BC8385B' is dependent on column 'COLUMNNAME'.
I have this scripts on multiple databases so this part 'DF__TABLENAME__COLUMNNAME__7BC8385B'
is on every database different.
I can make
ALTER TABLE TABLENAME
DROP CONSTRAINT DF__TABLENAME__COLUMNNAME__7BC8385B;
And it will work, but It will not be very effective use it manually on all DB, I need make the script which will alter this column on everywhere without needed to know that constraint name.

If you've got variable constraint names you'll have to generate the change script per database. If you've got faith in this you can put the resulting script into an sp_executesql call.
This is using the sys views to query the database structure and generate the script in the last result column.
declare #TableName nvarchar(128) = 'TABLENAME';
declare #ColumnName nvarchar(128) = 'COLUMNNAME';
SELECT t.name [table], c.name [column], typ.name [type]
, def.name [DefaultConstraint], def.definition [DefaultValue]
, 'ALTER TABLE [' + t.name + '] DROP CONSTRAINT [' + def.name + ']; ALTER TABLE [' + t.name + '] ALTER COLUMN [' + c.name + '] DATETIME; ALTER TABLE [' + t.name + '] ADD CONSTRAINT [DF_' + t.name + '_' + c.name + '] DEFAULT getdate() FOR [' + c.name + '];'
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
JOIN sys.types typ on c.user_type_id=typ.user_type_id
LEFT JOIN sys.default_constraints def on c.default_object_id=def.object_id
WHERE typ.name = 'date'
and t.name = #TableName and c.name = #ColumnName
order by t.name, c.name

Related

Add Primary Key constraint automatically

I have the following table InfoSchema which contains the SchemaName and the TableName of each table in my test database :
SchemaName TableName
dbo Employee
dbo Department
Function Company
Finance Payslips
Sub ProjectSub
I want to add for each table the constraint PrimaryKey to the column ending with ID or Id :
In dbo.Employee there is one column EmployeeId so the query will be like below :
ALTER TABLE dbo.Employee
ADD CONSTRAINT Employee_pk PRIMARY KEY (EmployeeId);
For Sub.ProjectSub there are 3 columns ending with Id :
ProjectId
CompanyId
SubId
The constraint will be added at the first column appearing in the structure of the table.
As I mention in my comment, you can use a dynamic statement to create the statements. I very strongly suggest looking over the SQL generated, however, so I do not include an EXEC sp_executesql statement here. PRINT or SELECT the value of #SQL and check it over first, then run the statements as you need:
DECLARE #SQL nvarchar(MAX),
#CRLF nchar(2) = NCHAR(13) + NCHAR(10);
SET #SQL = STUFF((SELECT #CRLF + #CRLF +
N'ALTER TABLE ' + QUOTENAME(s.[name]) + N'.' + QUOTENAME(t.[name]) + #CRLF +
N'ADD CONSTRAINT ' + QUOTENAME(CONCAT(t.[name],N'_PK')) + N' PRIMARY KEY (' + QUOTENAME(c.[name]) + N');'
FROM sys.schemas s
JOIN sys.tables t ON s.schema_id = t.schema_id
CROSS APPLY (SELECT TOP 1 *
FROM sys.columns c
WHERE c.object_id = t.object_id
AND c.name LIKE '%id'
ORDER BY c.column_id ASC) c
WHERE NOT EXISTS (SELECT 1
FROM sys.key_constraints k
WHERE k.[type] = 'PK'
AND k.parent_object_id = t.object_id)
FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,4,N'');
PRINT #SQL;
This assumes that the first column, ordinally, needs to be the PK, and it will not attempt to create a PK on a table that already has one.
Not possible. There is no automatism for this in SQL Server, so it will require at least a script to run over the db to identify tables and columns and issue modify statements. Which is not "automatic" as it will not RUN automatic - you need to run it in a second step.

Execute Dynamically Selected Query in SQL

I am using a Multi tenant Shared schema database, so i have so many schema,
Required:
I want to remove some schema; for that i have to remove all the CONSTRAINT of tables in that schema to delete a table. I got the the list of query to remove all the CONSTRAINT of a schema and the query to delete the tables from below code
Question:
From the below code i got a list of Queries,now i am copy that queries and executing that list of queries manually,can i do that automatically ?
Code
SET NOCOUNT ON;
DECLARE #SchemaName nvarchar(250)
SET #SchemaName='schemaname1'
--Step 1: Remove all CONSTRAINT
SELECT 'ALTER TABLE ' +'[' + s.name + '].[' + t.name + ']' +' DROP CONSTRAINT [' + f.name +']'
FROM sys.foreign_keys f
INNER JOIN sys.TABLES t ON f.parent_object_id=t.object_id
INNER JOIN sys.schemas s ON t.schema_id=s.schema_id
WHERE t.is_ms_shipped=0
and t.schema_id = schema_id(#SchemaName);
--Step 2: Drop all Tables
SELECT 'DROP TABLE ' + '[' + s.name + '].[' + t.name + ']'
FROM sys.TABLES t
INNER JOIN sys.schemas s ON t.schema_id=s.schema_id
WHERE t.is_ms_shipped=0 and t.schema_id = schema_id(#SchemaName);
Using COALESCE function we can turn multiple rows into a single string in SQL Server
Following code is working fine, to delete All the table in a Schema
SELECT * INTO #mytemp FROM INFORMATION_SCHEMA.SCHEMATA
WHERE [SCHEMA_NAME] in ('schemaname1','schemaname2','schemaname3')
WHILE (SELECT Count(*) FROM #mytemp) > 0
BEGIN
DECLARE #SCHEMA_NAME varchar(100)
SELECT #SCHEMA_NAME = [SCHEMA_NAME] FROM #mytemp
DECLARE #SQL VARCHAR(MAX)
SET #SQL='';
--Step 1: Remove all CONSTRAINT
SELECT #SQL= COALESCE(#SQL,'') +'ALTER TABLE ' +'[' + s.name + '].[' + t.name + ']' +' DROP CONSTRAINT [' + f.name +']'+ ' ; '
FROM sys.foreign_keys f
INNER JOIN sys.TABLES t ON f.parent_object_id=t.object_id
INNER JOIN sys.schemas s ON t.schema_id=s.schema_id
WHERE t.is_ms_shipped=0
and t.schema_id = schema_id(#SCHEMA_NAME);
--Step 2: Drop all Tables
SELECT #SQL= COALESCE(#SQL,'')+'DROP TABLE ' + '[' + s.name + '].[' + t.name + ']'+ ' ; '
FROM sys.TABLES t
INNER JOIN sys.schemas s ON t.schema_id=s.schema_id
WHERE t.is_ms_shipped=0 and t.schema_id = schema_id(#SCHEMA_NAME);
EXEC(#SQL)
--Custom Query End
DELETE #mytemp WHERE [SCHEMA_NAME] = #SCHEMA_NAME
END
DROP TABLE #mytemp

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;

How can I drop all indexes in a SQL database with one command?

So, how can I drop all indexes in a SQL database with one command? I have this command that will get me all the 20 or so drop statements, but how can I run all of those drop statements from this "result set"?
select * from vw_drop_idnex;
Another variation that gives me the same list is:
SELECT 'DROP INDEX ' + ix.Name + ' ON ' + OBJECT_NAME(ID) AS QUERYLIST
FROM sysindexes ix
WHERE ix.Name IS NOT null and ix.Name like '%pre_%'
I tried to do "exec(select cmd from vw_drop_idnex)" and it didn't work. I am looking for something that works like a for loop and runs the queries one by one.
-----------------------
With Rob Farleys help, final draft of the script is:
declare #ltr nvarchar(1024);
SELECT #ltr = ( select 'alter table '+o.name+' drop constraint '+i.name+';'
from sys.indexes i join sys.objects o on i.object_id=o.object_id
where o.type<>'S' and is_primary_key=1
FOR xml path('') );
exec sp_executesql #ltr;
declare #qry nvarchar(1024);
select #qry = (select 'drop index '+o.name+'.'+i.name+';'
from sys.indexes i join sys.objects o on i.object_id=o.object_id
where o.type<>'S' and is_primary_key<>1 and index_id>0
for xml path(''));
exec sp_executesql #qry
You're very close.
declare #qry nvarchar(max);
select #qry =
(SELECT 'DROP INDEX ' + quotename(ix.name) + ' ON ' + quotename(object_schema_name(object_id)) + '.' + quotename(OBJECT_NAME(object_id)) + '; '
FROM sys.indexes ix
WHERE ix.Name IS NOT null and ix.Name like '%prefix_%'
for xml path(''));
exec sp_executesql #qry
this worked for me
we skip sys indexes and for constraints
declare #qry nvarchar(max);
select #qry = (
select 'IF EXISTS(SELECT * FROM sys.indexes WHERE name='''+ i.name +''' AND object_id = OBJECT_ID(''['+s.name+'].['+o.name+']'')) drop index ['+i.name+'] ON ['+s.name+'].['+o.name+']; '
from sys.indexes i
inner join sys.objects o on i.object_id=o.object_id
inner join sys.schemas s on o.schema_id = s.schema_id
where o.type<>'S' and is_primary_key<>1 and index_id>0
and s.name!='sys' and s.name!='sys' and is_unique_constraint=0
for xml path(''));
exec sp_executesql #qry
From: Stephen Hill's Bloggie
DECLARE #indexName VARCHAR(128)
DECLARE #tableName VARCHAR(128)
DECLARE [indexes] CURSOR FOR
SELECT [sysindexes].[name] AS [Index],
[sysobjects].[name] AS [Table]
FROM [sysindexes]
INNER JOIN [sysobjects]
ON [sysindexes].[id] = [sysobjects].[id]
WHERE [sysindexes].[name] IS NOT NULL
AND [sysobjects].[type] = 'U'
--AND [sysindexes].[indid] > 1
OPEN [indexes]
FETCH NEXT FROM [indexes] INTO #indexName, #tableName
WHILE ##FETCH_STATUS = 0
BEGIN
--PRINT 'DROP INDEX [' + #indexName + '] ON [' + #tableName + ']'
Exec ('DROP INDEX [' + #indexName + '] ON [' + #tableName + ']')
FETCH NEXT FROM [indexes] INTO #indexName, #tableName
END
CLOSE [indexes]
DEALLOCATE [indexes]
GO
None of the answers quite suited my needs.
I needed one that will also drop indexes that backup unique or primary constraints (except if these can't be dropped as they back up a foreign key)
DECLARE #SqlScript NVARCHAR(MAX);
SELECT #SqlScript =
(
SELECT
'
BEGIN TRY
'+ CASE WHEN 1 IN (i.is_primary_key, i.is_unique_constraint) THEN
'
ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(i.object_id)) + '.' + QUOTENAME(t.name) + ' DROP CONSTRAINT ' + QUOTENAME(i.name) + ';'
else
'
DROP INDEX ' + QUOTENAME(i.name) + ' ON ' + QUOTENAME(OBJECT_SCHEMA_NAME(i.object_id)) + '.' + QUOTENAME(t.name)
END+'
END TRY
BEGIN CATCH
RAISERROR(''Could not drop %s on table %s'', 0,1, ' + QUOTENAME(i.name, '''') + ', ' + QUOTENAME(t.name, '''') + ')
END CATCH
'
FROM sys.indexes i
JOIN sys.tables t ON i.object_id = t.object_id
WHERE i.type_desc IN ('CLUSTERED', 'NONCLUSTERED' )
ORDER BY t.object_id, i.index_id DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)');
--Return script that will be run
SELECT #SqlScript AS [processing-instruction(x)]
FOR XML PATH('');
EXEC (#SqlScript);
Minor improvements to the accepted answer that I had to make in my own case, mostly to account for schemas:
declare #qry nvarchar(4000);
select #qry = (select 'drop index ['+s.name+'].['+o.name+'].['+i.name+'];'
from sys.indexes i join sys.objects o on i.object_id=o.object_id join sys.schemas s on o.schema_id=s.schema_id
where o.type<>'S' and is_primary_key<>1 and index_id>0 and s.name<>'sys'
for xml path(''));
exec sp_executesql #qry
Also: In my case it couldn't run in one go because the script becomes longer than 4000 characters. The only way I could think of to deal with that was to put a "top 20" on the inner select and execute it multiple times.
The "Final Draft" that OP posts as part of his question errors out if there are already zero indexes on any table in the DB. I needed to fix that.
Also, I wanted more control over the process than dropping all indexes on all tables, so I wrote the following stored proc to do it one table at a time:
CREATE PROCEDURE [dbo].[sp_DropAllIndexesOnTable]
#TableName varchar(1000)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #DropCommand1 nvarchar(4000)
DECLARE #DropCommand2 nvarchar(4000)
--Create Temp Table to hold the names and table names of all Clustered Indexes
SELECT o.name AS TableName, i.name AS IndexName
INTO #AllClustered
FROM sys.indexes i
INNER JOIN sys.objects o ON i.object_id=o.object_id
WHERE o.type <> 'S'
AND is_primary_key = 1
--Create Temp Table to hold the names and table names of all NonClustered Indexes
SELECT o.name AS TableName, i.name AS IndexName
INTO #AllNonClustered
FROM sys.indexes i
INNER JOIN sys.objects o ON i.object_id=o.object_id
WHERE o.type <> 'S'
AND is_primary_key <> 1
AND index_id > 0
--Create DROP CONSTRAINT command for the Primary Key Constraint if there is one
SELECT #DropCommand1 = ( SELECT 'ALTER TABLE dbo.['+ TableName +'] DROP CONSTRAINT ['+ IndexName +'];'
FROM #AllClustered
WHERE TableName = #TableName
FOR xml path('') );
--Create DROP INDEX command for the indexes on the table if there are any
SELECT #DropCommand2 = ( SELECT 'DROP INDEX [' + IndexName + '] ON dbo.['+ TableName +'];'
FROM #AllNonClustered
WHERE TableName = #TableName
FOR xml path('') );
IF (#DropCommand1 IS NULL AND #DropCommand2 IS NULL) PRINT 'No action taken, zero indexes found on table ' + #TableName
IF #DropCommand1 IS NOT NULL EXEC sp_executesql #DropCommand1
IF #DropCommand2 IS NOT NULL EXEC sp_executesql #DropCommand2
DROP TABLE IF EXISTS #AllClustered
DROP TABLE IF EXISTS #AllNonClustered
END
GO
I cycle through the specific tables in my DB which I want to drop indexes on using a loop, and I drop the indexes by calling this proc with the table name, and recreate better ones right after. This way, only one table at a time has no indexes.
The reason I do this and the number of tables I do it on would make your head spin, but I definitely needed a proc like this!
SELECT 'DROP INDEX [' + IX.NAME + '] ON ' + OBJECT_NAME(IX.OBJECT_ID) + '; '
FROM SYS.INDEXES IX
JOIN SYS.OBJECTS O ON IX.OBJECT_ID = O.OBJECT_ID
INNER JOIN SYS.SCHEMAS S ON O.SCHEMA_ID = S.SCHEMA_ID
WHERE
IX.NAME IS NOT NULL
AND O.TYPE <> 'S'
AND IS_PRIMARY_KEY <> 1
AND INDEX_ID > 0
AND S.NAME != 'SYS' AND S.NAME!= 'SYS' AND IS_UNIQUE_CONSTRAINT = 0
Modify conditions according to your needs
If u want to delete PK constraints, you will get this message if you try to drop index:
An explicit DROP INDEX is not allowed on index... It is being used for PRIMARY KEY constraint enforcement.
Then, use this...
SELECT 'ALTER TABLE [' + O.NAME + '] DROP CONSTRAINT ' + IX.NAME + '; '
FROM SYS.INDEXES IX
JOIN SYS.OBJECTS O ON IX.OBJECT_ID = O.OBJECT_ID
INNER JOIN SYS.SCHEMAS S ON O.SCHEMA_ID = S.SCHEMA_ID
WHERE
IX.NAME IS NOT NULL
AND O.TYPE <> 'S'
AND INDEX_ID > 0
AND S.NAME != 'SYS' AND S.NAME!= 'SYS'

Dropping unnamed constraints

I've created some foreign keys without an explicit name.
Then I've found SQL generated crazy names like FK__Machines__IdArt__760D22A7. Guess they will be generated with different names at different servers.
Is there any nice function to drop the unnamed FK constraints passing as arguments the tables and the fields in question?
For dropping an individual unnamed default constrain on a column use the following code:
DECLARE #ConstraintName VARCHAR(256)
SET #ConstraintName = (
SELECT obj.name
FROM sys.columns col
LEFT OUTER JOIN sys.objects obj
ON obj.object_id = col.default_object_id
AND obj.type = 'F'
WHERE col.object_id = OBJECT_ID('TableName')
AND obj.name IS NOT NULL
AND col.name = 'ColunmName'
)
IF(#ConstraintName IS NOT NULL)
BEGIN
EXEC ('ALTER TABLE [TableName] DROP CONSTRAINT ['+#ConstraintName+']')
END
If you want to do this for a default column, which is probably more common than the original question and I'm sure a lot of people will land on this from a Google search, then just change the line:
obj.type = 'F'
to
obj.type = 'D'
There is not a built in procedure to accomplish this, but you can build your own using the information in the information_schema views.
Table based example
Create Proc dropFK(#TableName sysname)
as
Begin
Declare #FK sysname
Declare #SQL nvarchar(4000)
Declare crsFK cursor for
select tu.Constraint_Name from
information_schema.constraint_table_usage TU
LEFT JOIN SYSOBJECTS SO
ON TU.Constraint_NAME = SO.NAME
where xtype = 'F'
and Table_Name = #TableName
open crsFK
fetch next from crsFK into #FK
While (##Fetch_Status = 0)
Begin
Set #SQL = 'Alter table ' + #TableName + ' Drop Constraint ' + #FK
Print 'Dropping ' + #FK
exec sp_executesql #SQL
fetch next from crsFK into #FK
End
Close crsFK
Deallocate crsFK
End
Although Gunner's answer puts people on the right track if you want to drop an actual DEFAULT constraint rather than an FKey constraint (which is what brought ME here too!) there are problems with it.
I think this fixes them all. (T-SQL)
CREATE PROC #DropDefaultConstraint #SchemaName sysname, #TableName sysname, #ColumnName sysname
AS
BEGIN
DECLARE #ConstraintName sysname;
SELECT #SchemaName = QUOTENAME(#SchemaName)
, #TableName = QUOTENAME(#TableName);
SELECT #ConstraintName = QUOTENAME(o.name)
FROM sys.columns c
JOIN sys.objects o
ON o.object_id = c.default_object_id
WHERE c.object_id = OBJECT_ID(#SchemaName+'.'+#TableName)
AND c.name = #ColumnName;
IF #ConstraintName IS NOT NULL
EXEC ('ALTER TABLE ' + #SchemaName + '.' + #TableName + ' DROP CONSTRAINT ' + #ConstraintName + '');
END
This will let you drop a specific foreign key constraint based on tablename + column name
After trying out the other answers I just had a poke around in the system tables until I found something likely looking.
The one you want is Constraint_Column_Usage which according to the docs Returns one row for each column in the current database that has a constraint defined on the column.
I've joined it to sys.objects to just get foreign keys.
In a procedure (this borrows from the other answers. cheers guys!):
Create Proc yourSchema.dropFK(#SchemaName NVarChar(128), #TableName NVarChar(128), #ColumnName NVarChar(128))
as
Begin
DECLARE #ConstraintName nvarchar(128)
SET #ConstraintName = (
select c.Constraint_Name
from Information_Schema.Constraint_Column_usage c
left join sys.objects o
on o.name = c.Constraint_Name
where c.TABLE_SCHEMA = #SchemaName and
c.Table_name = #TableName and
c.Column_Name = #ColumnName and
o.type = 'F'
)
exec ('alter table [' + #SchemaName + '].[' + #TableName + '] drop constraint [' + #ConstraintName + ']')
End
Neither of these worked for me so I had to come up with this to work on mssql server version both 12 and 14.
First, inspect the name given to the FK by the RDBMS, it has the same prefix and body but differs only in suffix hash.
Second, select names of these constraints.
Third, exec alter command that drops them.
Finally you can drop the column or table blocked by these
BEGIN TRANSACTION;
DECLARE #ConstraintName nvarchar(200)
SELECT #ConstraintName = name
FROM sys.objects
WHERE type_desc = 'FOREIGN_KEY_CONSTRAINT'
AND name LIKE 'FK__table_col_shortcut1___%'
EXEC('ALTER TABLE table1 DROP CONSTRAINT ' + #ConstraintName)
SELECT #ConstraintName = name
FROM sys.objects
WHERE type_desc = 'FOREIGN_KEY_CONSTRAINT'
AND name LIKE 'FK__table_col_shortcut2___%'
EXEC('ALTER TABLE table2 DROP CONSTRAINT ' + #ConstraintName)
SELECT #ConstraintName = name
FROM sys.objects
WHERE type_desc = 'FOREIGN_KEY_CONSTRAINT'
AND name LIKE 'FK__table_col_shortcut3___%'
EXEC('ALTER TABLE table3 DROP CONSTRAINT ' + #ConstraintName)
DROP TABLE table_referenced;
COMMIT TRANSACTION;
Lesson learnt, I will always create constraints explicitly from now on!
This will generate a script to rename default constraints to use the pattern
DF__table_name__column_name
SELECT 'EXEC sp_rename ''dbo.' + dc.name + ''', ''DF__' + t.name + '__' + c.name + '''' AS the_script,
t.name AS table_name,
c.name AS column_name,
dc.name AS old_constraint_name
FROM
sys.default_constraints dc
INNER JOIN sys.tables t
ON dc.parent_object_id = t.object_id
INNER JOIN sys.columns c
ON dc.parent_column_id = c.column_id
AND t.object_id = c.object_id
WHERE
dc.name <> 'DF__' + t.name + '__' + c.name