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


68

我知道语法:

ALTER TABLE [TheTable] DROP CONSTRAINT [TheDefaultConstraint]

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

Answers:


48

如果要手动执行此操作,则可以使用Management Studio来找到它(在表内的Constraints节点下)。

要使用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。


当我首先找到表的objectIDDECLARE @ParentObjectId INT = (select OBJECT_ID from sys.objects where name = 'ParentTable' AND type = 'U') 并将其添加 WHERE parent_object_id = @ParentObjectId 到查询中时,第一个查询在SQL 2008 r2中运行良好 。否则,您将获得数据库中的所有默认约束。
洪流2015年

很好,但是没有显示表所在的架构。如果您向sys.schemas添加了联接,那将会很好。
AperioOculus '02

如果知道表名,则将WHERE子句添加到SELECT中,这样就不必搜索可能很长的表名列表。自动生成的名称似乎包含表名和列名的截断部分,这将使您标识正确的约束。祝好运!
ohgodnotanotherone

64

您可以使用以下代码自动执行此操作:

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';
克里斯-

8
我只是不明白为什么MS SQL不会自动删除默认约束。
蒂姆(Tim)

1
该自动化脚本对于任何自带的数据库模式更新引擎都是必不可少的。我想知道EF迁移工具是如何做到的?SQL Server为匿名默认值生成名称并要求您知道/获取该名称以便再次更改或删除该名称的根本缺陷是,这早在tsql语法本身中就已解决。但是它仍然存在于sql2016中。@Tim是,或者至少是强制删除的语法。
Cee McSharpface '16

@dlatikay EF不处理默认约束。默认情况下,它不会创建它们(因为无法设置属性或流畅的api),但是如果您手动添加它们,EF将不会检查其他更改是否将其删除。我不知道自动迁移是否成立。
蒂姆(Tim)

1
@Tim当前版本的EF可以做到。我出于好奇而查了一下,他们的方法非常相似:他们从sys.default_constraints;检索名称。看看577行及以下,此处
Cee McSharpface '16


3

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

或者,您可能可以通过Management Studio做到这一点。


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并执行它来完成的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.