如何删除具有未命名默认值约束和未知索引的列

4

如何确定一列是否存在默认约束及其名称,并确定任何索引的名称,以便在删除该列之前先删除它们?


如何删除带有未命名默认约束和索引的列?如果主题行中没有“如何”,请原谅,因为该网站上关于这些主题的信息混乱不堪,而且常见问题解答说您可以回答自己的问题,所以我想发布一个简明的解决方案,以便帮助其他人。 - avenmore
将来,您可以按照以下流程操作: --> 编写问题 --> 发布问题 --> 编写答案(在答案部分) --> 发布答案 --> 标记为正确答案。虽然如果您喜欢博客,这听起来像是一个很棒的主题。 - Michael J Swart
感谢指点。已经修改符合要求。 - avenmore
1个回答

9
以下实用程序过程将完成此任务。
if (exists (select * from [dbo].sysobjects where (id = object_id(N'[dbo]._spDropDefaultValueConstraint')) and (xtype = 'P')))
 drop procedure [dbo]._spDropDefaultValueConstraint
GO

create procedure [dbo]._spDropDefaultValueConstraint
 @TableName varchar(256),
 @ColumnName varchar(256)
as
/* This proc will drop the default value constraint on
 a column even when you don't know what its name is.
*/
declare @ConstraintName varchar(256)
set @ConstraintName = (
 select 
  dobj.name
 from sys.columns col 
  left outer join sys.objects dobj 
   on dobj.object_id = col.default_object_id and dobj.type = 'D' 
 where col.object_id = object_id('[dbo].'+@TableName) 
 and dobj.name is not null
 and col.name = @ColumnName)

if(isnull(@ConstraintName, '') <> '')
 exec('alter table [dbo].['+@TableName+'] drop constraint ['+@ConstraintName+']')

GO

-------------------------------------------------------------------------------------------

if (exists (select * from [dbo].sysobjects where (id = object_id(N'[dbo]._spDropIndexesForColumn')) and (xtype = 'P')))
 drop procedure [dbo]._spDropIndexesForColumn
GO

create procedure [dbo]._spDropIndexesForColumn
 @TableName varchar(256),
 @ColumnName varchar(256)
as
/* This proc will drop all indexes on a column, both indexes
 and unique constraints as well as multi-part indexes that reference it.
*/
declare @IndexName varchar(256)
declare @IsPrimaryKey bit
declare @IsUniqueConstraint bit

declare crIndexes cursor for
 select
  ind.name, ind.is_primary_key, ind.is_unique_constraint
 from 
  sys.indexes ind
  inner join sys.index_columns ic on ind.object_id = ic.object_id and ind.index_id = ic.index_id
  inner join sys.columns col on ic.object_id = col.object_id and ic.column_id = col.column_id 
  inner join sys.tables t on ind.object_id = t.object_id
 where
  t.name = @TableName and
  col.name = @ColumnName      
open crIndexes
fetch next from crIndexes into @IndexName, @IsPrimaryKey, @IsUniqueConstraint
while(@@fetch_status = 0) begin
 if(@IsPrimaryKey = 1) or (@IsUniqueConstraint = 1)
  exec('alter table [dbo].['+@TableName+'] drop constraint ['+@IndexName+']')
 else
  exec('drop index [dbo].['+@TableName+'].['+@IndexName+']')
 fetch next from crIndexes into @IndexName, @IsPrimaryKey, @IsUniqueConstraint
end
close crIndexes
deallocate crIndexes

GO

-------------------------------------------------------------------------------------------

if (exists (select * from [dbo].sysobjects where (id = object_id(N'[dbo]._spDropColumn')) and (xtype = 'P')))
 drop procedure [dbo]._spDropColumn
GO

create procedure [dbo]._spDropColumn
 @TableName varchar(256),
 @ColumnName varchar(256)
as
/* This proc will drop a column (first dropping the default value
 constraint and any indexes if they exist) if it exists.
*/
if (exists (select * from [dbo].sysobjects where (id = object_id('[dbo].'+@TableName)) and (xtype = 'U'))) and
   (exists (select * from [dbo].syscolumns where (id = object_id('[dbo].'+@TableName)) and (name = @ColumnName))) begin
 exec [dbo]._spDropIndexesForColumn @TableName, @ColumnName
 exec [dbo]._spDropDefaultValueConstraint @TableName, @ColumnName
 exec('alter table [dbo].['+@TableName+'] drop column ['+@ColumnName+']')
end
GO

然后,你可以轻松地按照如下方式调用它:

exec [dbo]._spDropColumn 'TableName', 'ColumnName'

我没有研究过外键约束,因为我们不使用它们,但也许它们也可以被包含在内。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接