如何在T-SQL中删除默认值或类似约束?

72

我知道该语法:

ALTER TABLE [TheTable] DROP CONSTRAINT [TheDefaultConstraint]

但是我不知道默认约束的名称,我该如何删除它?(也就是说,在CREATE TABLE时自动生成了它。)

6个回答

69
你可以使用这段代码来自动完成它:
DECLARE @tableName VARCHAR(MAX) = '<MYTABLENAME>'
DECLARE @columnName VARCHAR(MAX) = '<MYCOLUMNAME>'
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 = @columnName AND object_id = OBJECT_ID(@tableName))
IF @ConstraintName IS NOT NULL
    EXEC('ALTER TABLE '+@tableName+' DROP CONSTRAINT ' + @ConstraintName)

只需将<MYTABLENAME><MYCOLUMNNAME>替换为相应的内容即可。


5
为了懒人(和微软的SQL Server开发人员),向这个答案致敬,将前两行替换为 CREATE PROCEDURE dbo.DropColumnDefaultOrConstraint @tableName VARCHAR(MAX), @columnName VARCHAR(MAX) AS ,然后用 BEGINEND 包裹,并使用 EXEC DropColumnDefaultOrConstraint 'tablename', 'columnname'; - Chris
10
我不明白为什么 MS SQL 不会自动删除默认约束。 - Tim
1
这个自动化脚本对于任何自定义数据库模式更新引擎都是必不可少的。我想知道EF迁移工具是如何做到的?底层缺陷是,SQL服务器为匿名默认值生成名称,并要求您知道/获取该名称才能再次更改或删除它,这是一个问题,早在tsql语法本身就应该解决了。但它仍然存在于sql2016中。@Tim 是的,或者至少有一种语法来强制删除。 - Cee McSharpface
@dlatikay EF不处理默认约束。它不会默认创建它们(因为无法使用属性或流畅的API设置它们),但是如果您手动添加它们,EF将永远不会检查以删除它们对于其他更改。 我不知道这在自动迁移中是否成立。 - Tim
1
@Tim 当前版本的EF可以做到这一点。我出于好奇查了一下,他们的方法非常相似:从sys.default_constraints中检索名称;请看第577行及其后面的内容,此处 - Cee McSharpface
@dlatikay 哦,谢谢,知道他们在EF Core中修复了这个问题很好。我还在使用6版。值得升级吗? - Tim

50

如果您想手动完成此操作,可以使用管理工具查找它(在表内的约束节点下)。

要使用SQL完成此操作:

  • 如果约束是默认约束,则可以使用sys.default_constraints找到它:

  • SELECT OBJECT_NAME(parent_object_id) AS TableName, name AS ConstraintName
    FROM sys.default_constraints ORDER BY TableName, ConstraintName
    
    如果你还想寻找其他约束条件(如检查、唯一性、外键、默认值、主键),你可以使用 sysconstraints
    SELECT OBJECT_NAME(id) AS TableName, OBJECT_NAME(constid) AS ConstraintName
    FROM sysconstraints ORDER BY TableName, ConstraintName
    
    您没有说明在使用哪个版本的SQL Server。上述代码在SQL 2005和SQL 2008上都可以运行。

当我首先使用以下代码在SQL 2008 r2中找到表的objectID时,第一个查询非常有效:DECLARE @ParentObjectId INT = (select OBJECT_ID from sys.objects where name = 'ParentTable' AND type = 'U')并将以下代码添加到查询中:WHERE parent_object_id = @ParentObjectId否则,您将获取数据库中所有默认约束。 - Torrents
这很好,但它没有显示表所在的模式。如果您添加了sys.schemas的连接,那就太好了。 - AperioOculus
如果您知道表名,请在SELECT语句中添加WHERE子句,这样您就不必在可能很长的表名列表中搜索。自动生成的名称似乎包含表和列名称的截断部分,这将让您识别正确的约束条件。祝你好运! - Marcell

4

您可以通过sp_help [表名]查找约束的名称,然后按名称删除它。

或者您可以通过管理工具完成此操作。


4
您可以使用sys.check_constraints目录视图查找它。

2

要单独在一行中使用一个表和列,请使用以下内容:

declare @sql nvarchar(max); set @sql = ''; SELECT @sql+='ALTER TABLE [dbo].[YOURTABLENAME] DROP CONSTRAINT ' + ((SELECT OBJECT_NAME(constid) FROM sysconstraints WHERE OBJECT_NAME(id) = 'YOURTABLENAME'AND colid IN (SELECT ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS Where Table_Name = 'YOURTABLENAME' and COLUMN_NAME = 'YOURCOLUMNNAM'))) + ';'; EXEC sp_executesql @sql;

如果您在列上有多个约束条件,您将需要区分您想要的约束条件,但是如果您只有一个默认约束条件,那么这将起到作用。

请查看 information_schema 中提供的其他列,以进一步区分。


0

这里是我自己的版本,它会删除所有依赖约束 -- 默认约束(如果存在)和所有受影响的检查约束(正如SQL标准所建议的,以及其他一些数据库也是如此)

declare @constraints varchar(4000);
declare @sql varchar(4000);
with table_id_column_position as (
   select object_id table_id, column_id column_position
      from sys.columns where object_id is not null and object_id = object_id('TableName') and name = 'ColumnToBeDropped'
)
select @constraints = coalesce(@constraints, 'constraint ') + '[' + name + '], '
from sysobjects 
where (
  -- is CHECK constraint
  type = 'C' 
  -- dependeds on the column
  and id is not null
  and id in (
      select object_id --, object_name(object_id)
      from sys.sql_dependencies, table_id_column_position 
      where object_id is not null
      and referenced_major_id = table_id_column_position.table_id
      and referenced_minor_id = table_id_column_position.column_position
    )
) OR (
  -- is DEFAULT constraint
  type = 'D'
  and id is not null
  and id in (
    select object_id
    from sys.default_constraints, table_id_column_position
     where object_id is not null
     and parent_object_id = table_id_column_position.table_id
     and parent_column_id = table_id_column_position.column_position
  )
);
set @sql = 'alter table TableName drop ' + coalesce(@constraints, '') + ' column ColumnToBeDropped';
exec @sql

注意:上面的代码中TableNameColumnToBeDropped都出现了两次。

这个方法是通过构建单个ALTER TABLE TableName DROP CONSTRAINT c1, ..., COLUMN ColumnToBeDropped语句并执行它来实现的。


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