ALTER TABLE DROP COLUMN 失败,因为一个或多个对象访问此列

Posted

技术标签:

【中文标题】ALTER TABLE DROP COLUMN 失败,因为一个或多个对象访问此列【英文标题】:ALTER TABLE DROP COLUMN failed because one or more objects access this column 【发布时间】:2017-09-18 20:26:54 【问题描述】:

我正在尝试这样做:

ALTER TABLE CompanyTransactions DROP COLUMN Created

但我明白了:

消息 5074,第 16 级,状态 1,第 2 行 对象“DF__CompanyTr__Creat__0CDAE408”依赖于“已创建”列。 消息 4922,第 16 级,状态 9,第 2 行 ALTER TABLE DROP COLUMN 创建失败,因为一个或多个对象访问此列。

这是一个代码优先表。不知何故,迁移变得一团糟,我正在尝试手动回滚一些更改。

知道这是什么:

DF__CompanyTr__Creat__0CDAE408

【问题讨论】:

它没有那么简单。您将无法在更高的环境中查看实际的约束名称。 【参考方案1】:

在删除列之前,您必须从列中删除 constraints。您引用的名称是default constraint

例如

alter table CompanyTransactions drop constraint [df__CompanyTr__Creat__0cdae408];
alter table CompanyTransactions drop column [Created];

【讨论】:

令人沮丧的是 Entity Framework 没有为我们处理这些问题。 @chakeda 我同意 我也有类似的情况。问题是我的应用程序部署到很多机器上,并且所有自动生成的约束都有不同的名称。如何处理这种情况?将一个从 information_schema 生成 sql 的长脚本添加到迁移中感觉不是一个干净而好的选择。 @MantasDaškevičius 最好的选择是命名约束而不是使用自动生成的名称。【参考方案2】:

@SqlZim 的回答是正确的,但只是为了解释为什么会发生这种情况。我有类似的问题,这是由非常无辜的事情引起的:向列添加默认值

ALTER TABLE MySchema.MyTable ADD 
  MyColumn int DEFAULT NULL;

但在 MS SQL Server 领域,列的默认值是 CONSTRAINT。和每个约束一样,它有一个标识符。如果在 CONSTRAINT 中使用列,则不能删除它。

因此,您实际上可以避免此类问题的方法是始终为您的默认约束提供一个显式名称,例如:

ALTER TABLE MySchema.MyTable ADD 
  MyColumn int NULL,
  CONSTRAINT DF_MyTable_MyColumn DEFAULT NULL FOR MyColumn;

您仍然必须在删除列之前删除约束,但您将至少预先知道它的名称

【讨论】:

要添加到@malloc4k 的答案...您可以展开 SQL Server 2016 中的“约束”文件夹,它将显示“默认”约束名称。【参考方案3】:

正如已经写在答案中的那样,您需要删除与您尝试删除的所有列相关的约束(由 sql 自动创建)。

执行以下步骤来做必要的事情。

    使用 sp_helpconstraint 获取所有约束的名称,这是一个系统存储过程实用程序 - 按照 exec sp_helpconstraint '&lt;your table name&gt;' 执行 一旦您获得约束的名称,然后复制该约束名称并执行下一条语句,即alter table <your_table_name> drop constraint <constraint_name_that_you_copied_in_1>(它只是这种或类似的格式) 删除约束后,您可以使用常规方法删除 1 列或多列,例如 Alter table &lt;YourTableName&gt; Drop column column1, column2

【讨论】:

【参考方案4】:

当您更改列 datatype 时,您需要为每个数据库更改 constraint key

  alter table CompanyTransactions drop constraint [df__CompanyTr__Creat__0cdae408];

【讨论】:

@user2513019 别忘了点赞它对你有帮助:)【参考方案5】:

你需要做几件事:

    您首先需要检查约束是否存在于信息架构中 那么你需要通过加入 sys.default_constraints 和 sys.columns 来查询 如果列和 default_constraints 具有相同的对象 ID 当您在第 2 步中加入时,您将从 default_constraints 中获取约束名称。你放弃那个约束。这是我做的一个这样的滴的例子。
-- 1. Remove constraint and drop column
IF EXISTS(SELECT *
          FROM INFORMATION_SCHEMA.COLUMNS
          WHERE TABLE_NAME = N'TABLE_NAME'
            AND COLUMN_NAME = N'LOWER_LIMIT')
   BEGIN
    DECLARE @sql NVARCHAR(MAX)
    WHILE 1=1
        BEGIN
            SELECT TOP 1 @sql = N'alter table [TABLE_NAME] drop constraint ['+dc.name+N']'
            FROM sys.default_constraints dc
            JOIN sys.columns c
            ON c.default_object_id = dc.object_id
            WHERE dc.parent_object_id = OBJECT_ID('[TABLE_NAME]') AND c.name = N'LOWER_LIMIT'
            IF @@ROWCOUNT = 0
                BEGIN
                    PRINT 'DELETED Constraint on column LOWER_LIMIT'
                    BREAK
                END
        EXEC (@sql)
    END;
    ALTER TABLE TABLE_NAME DROP COLUMN LOWER_LIMIT;
    PRINT 'DELETED column LOWER_LIMIT'
   END
ELSE
   PRINT 'Column LOWER_LIMIT does not exist'
GO

【讨论】:

【参考方案6】:

除了接受的答案之外,如果您使用 Entity Migrations 来更新数据库,则应在迁移文件中 Up() 函数的开头添加此行:

Sql("alter table dbo.CompanyTransactions drop constraint [df__CompanyTr__Creat__0cdae408];");

您可以在以FK_dbo.开头的nuget数据包管理器控制台的错误中找到约束名称

【讨论】:

【参考方案7】:

我遇到了同样的问题,这是对我有用的脚本,该脚本使用了一个由句点“.”分隔的两部分名称的表格。

使用 [数据库名称] 走 ALTER TABLE [TableNamePart1].[TableNamePart2] 删除约束 [DF__ TableNamePart1D__ColumnName__5AEE82B9] 走 ALTER TABLE [TableNamePart1].[TableNamePart1] DROP COLUMN [ColumnName] 去吧

【讨论】:

【参考方案8】:

我需要用 Guid 替换 INT 主键。经过几次失败的尝试后,下面的 EF 代码对我有用。如果您急于设置 defaultValue... 您最终会得到一个 Guid 和现有记录的键。

protected override void Up(MigrationBuilder migrationBuilder)
        
            migrationBuilder.DropUniqueConstraint("PK_Payments", "Payments");

            migrationBuilder.DropColumn(
                name: "PaymentId",
                table: "Payments");

            migrationBuilder.AddColumn<Guid>(
                name: "PaymentId",
                table: "Payments",
                type: "uniqueidentifier",
                defaultValueSql: "NewId()",
                nullable: false);

【讨论】:

以上是关于ALTER TABLE DROP COLUMN 失败,因为一个或多个对象访问此列的主要内容,如果未能解决你的问题,请参考以下文章

MVC - ALTER TABLE DROP COLUMN 失败,因为一个或多个对象访问此列

Oracle 11g XE "alter table drop column" 导致 ORA-00600

在 Hive CLI 上执行“alter table table_name drop partition(part_column < value)”时出现空指针错误

ALTER TABLE - 修改表的定义

数据库CRUD操作

我如何知道数据库触发器是 DROP_TABLE 还是 ALTER_TABLE?