【问题标题】:How do you drop a default value or similar constraint in T-SQL?如何在 T-SQL 中删除默认值或类似约束?
【发布时间】:2010-11-10 12:26:54
【问题描述】:

我知道语法:

ALTER TABLE [TheTable] DROP CONSTRAINT [TheDefaultConstraint]

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

【问题讨论】:

    标签: sql tsql constraints default


    【解决方案1】:

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

    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)
    

    只需根据需要替换 &lt;MYTABLENAME&gt; 和 &lt;MYCOLUMNNAME&gt;。

    【讨论】:

    • 对于懒惰的人,(和微软的 SQL Server 开发人员),为了向这个答案致敬,用CREATE PROCEDURE dbo.DropColumnDefaultOrConstraint @tableName VARCHAR(MAX), @columnName VARCHAR(MAX) AS 替换前两行,然后用BEGIN 和END 换行并使用EXEC DropColumnDefaultOrConstraint 'tablename', 'columnname';
    • 我只是不明白为什么 MS SQL 不会自动删除默认约束。
    • 这个自动化脚本对于任何滚动你自己的数据库模式更新引擎都是必不可少的。我想知道EF迁移工具是如何做到的?潜在的缺陷,即 SQL 服务器为匿名默认值生成名称并要求您知道/获取该名称以便再次更改或删除它,这是一个早就应该在 tsql 语法本身中解决的问题。但它仍然存在于 sql2016 中。 @Tim 是的,或者至少是强制删除的语法。
    • @dlatikay EF 不处理默认约束。默认情况下它不会创建它们(因为无法使用属性或流畅的 api 设置它们),但如果您手动添加它们,EF 将永远不会检查以在其他更改时删除它们。我不知道这是否适用于自动迁移。
    • @Tim 当前版本的 EF 可以做到。出于好奇,我查了一下,他们的做法非常相似:他们从sys.default_constraints 中检索名称;查看第 577 行及以下,here
    【解决方案2】:

    如果您想手动执行此操作,可以使用 Management Studio 找到它(在表内的约束节点下)。

    使用 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 上均适用。

    【讨论】:

    • 当我首先使用DECLARE @ParentObjectId INT = (select OBJECT_ID from sys.objects where name = 'ParentTable' AND type = 'U') 找到表的objectID 并将WHERE parent_object_id = @ParentObjectId 添加到查询时,第一个查询在SQL 2008 r2 中运行良好。否则,您将获得数据库中的所有默认约束。
    • 这很好,但它没有显示表所在的架构。如果您添加到 sys.schemas 的连接会很好。
    • 如果您知道表名,请在 SELECT 中添加 WHERE 子句,这样您就不必在可能很长的表名列表中进行搜索。自动生成的名称似乎包含表和列名称的截断部分,这将让您识别正确的约束。祝你好运!
    【解决方案3】:

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

    或者您也可以通过 Management Studio 执行此操作。

    【讨论】:

      【解决方案4】:

      或者您可以使用 sys.check_constraints 目录视图找到它。

      【讨论】:

        【解决方案5】:

        对于单行中的单个表和列,请使用以下内容

        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 中可用的其他列,以便您进一步区分。

        【讨论】:

          【解决方案6】:

          这是我自己的版本,它删除了所有依赖约束——默认约束(如果存在)和所有受影响的检查约束(正如 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
          

          (注意:TableName 和 ColumnToBeDropped 在上面的代码中都出现了两次)

          这通过构造单个ALTER TABLE TableName DROP CONSTRAINT c1, ..., COLUMN ColumnToBeDropped 并执行它来工作。

          【讨论】:

            猜你喜欢
            • 2012-06-02
            • 2012-06-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多