【问题标题】:The object 'DF__*' is dependent on column '*' - Changing int to double对象 'DF__*' 取决于列 '*' - 将 int 更改为 double
【发布时间】:2013-10-27 23:04:19
【问题描述】:

基本上,我在我的 EF 数据库中获得了一个具有以下属性的表:

public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public string WatchUrl { get; set; }
public int Year { get; set; }
public string Source { get; set; }
public int Duration { get; set; }
public int Rating { get; set; }
public virtual ICollection<Category> Categories { get; set; }

它工作正常,但是当我将 Rating 的 int 更改为 double 时,我在更新数据库时收到以下错误:

对象“DF_电影_Rating__48CFD27E”依赖于“评分”列。 ALTER TABLE ALTER COLUMN 评级失败,因为一个或多个对象访问此列。

有什么问题?

【问题讨论】:

  • 删除约束 DF_Movies_Rating__48CFD27E 然后更改字段的类型
  • @JoeTaras 但我从来没有创建过一个名为那个的约束。它是什么,我在哪里可以找到它?
  • 当你创建一个字段时,DBMS 会自动创建一个约束。如果你扩展你的表信息,你会在约束部分找到它。告诉我你是否能找到;)

标签: sql sql-server database entity-framework entity-framework-4


【解决方案1】:

试试这个:

在更改字段类型之前移除约束DF_Movies_Rating__48CFD27E

约束通常由 DBMS (SQL Server) 自动创建。

要查看与表关联的约束,请在对象资源管理器中展开表属性,然后是类别约束,如下所示:

您必须在更改字段类型之前移除约束。

【讨论】:

  • @ManirajSS: ALTER TABLE yourtable DROP CONSTRAINT DF_Movies_Rating__48CFD27E
  • 是什么触发了约束的创建?我有一堆,我真的不想要它们!
  • 嗯,如果我想使用我的框架 (Laravel) 的数据库迁移和 dropColumn 那里该怎么办?我不知道如何删除由 SQL 服务器自动生成的具有神秘名称的约束:(
  • 我确定:我删除了它,文件夹 Constraints 变为空,当我运行应用程序或调用 update-database 时,它会重新创建自己,我发布了这个问题:stackoverflow.com/questions/40267769/…
  • 为什么 SQLServer 不隐式删除约束?毕竟,它确实是隐式创建的!
【解决方案2】:

我将此添加为响应以解释约束来自何处。 我试图在 cmets 中做到这一点,但在那里很难很好地编辑:-/

如果您创建(或更改)具有默认值的列的表,它将为您创建约束。

例如,在您的表格中可能是:

CREATE TABLE Movie (
    ...
    rating INT NOT NULL default 100
)

它将为默认 100 创建约束。

如果你改为这样创建它

CREATE TABLE Movie (
  name VARCHAR(255) NOT NULL,
  rating INT NOT NULL CONSTRAINT rating_default DEFAULT 100
);

然后你会得到一个命名良好的约束,当你改变表时更容易引用它。

ALTER TABLE Movie DROP CONSTRAINT rating_default;
ALTER TABLE Movie ALTER COLUMN rating DECIMAL(2) NOT NULL;
-- sets up a new default constraint with easy to remember name
ALTER TABLE Movie ADD CONSTRAINT rating_default DEFAULT ((1.0)) FOR rating;

您可以组合最后两条语句,以便在一行中更改列并将约束命名(如果它是现有表,则必须这样做)

【讨论】:

  • 感谢您添加有关如何通过首先命名所有约束来避免该问题的信息。 (即避免丢弃随机命名约束的问题)
【解决方案3】:

这是tsql方式

 ALTER TABLE yourtable DROP CONSTRAINT constraint_name     -- DF_Movies_Rating__48CFD27E

为了完整起见,这只是将@Joe Taras 的评论显示为答案

【讨论】:

    【解决方案4】:

    由于约束具有不可预测的名称,您可以编写特殊脚本(DropConstraint)在不知道它的名称的情况下将其删除(在 EF 6.1.3 测试):

    public override void Up()
    {    
        DropConstraint();
        AlterColumn("dbo.MyTable", "Rating", c => c.Double(nullable: false));
    }
    
    private void DropConstraint()
    {
        Sql(@"DECLARE @var0 nvarchar(128)
              SELECT @var0 = name
              FROM sys.default_constraints
              WHERE parent_object_id = object_id(N'dbo.MyTable')
              AND col_name(parent_object_id, parent_column_id) = 'Rating';
              IF @var0 IS NOT NULL
                  EXECUTE('ALTER TABLE [dbo].[MyTable] DROP CONSTRAINT [' + @var0 + ']')");
    }
    
    public override void Down()
    {            
        AlterColumn("dbo.MyTable", "Rating", c => c.Int(nullable: false));    
    }
    

    【讨论】:

    • 这个答案在基于迁移的环境中非常有效,您无法对约束名称进行硬编码。
    • 如果你为 AlterColumn 创建了一个包装器/扩展/重载函数——比如 AlterColumnX——你可以在其中包含 DropConstraint 逻辑——你可以传入表名和列名,这样你就没有再写一遍。
    【解决方案5】:

    MS SQL Studio 会在您删除列时进行处理,但如果您需要以编程方式删除约束,这是一个简单的解决方案

    这是一个代码 sn-p,它将删除具有默认约束的列:

    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 = N'__ColumnName__' AND object_id = OBJECT_ID(N'__TableName__'))
    IF @ConstraintName IS NOT NULL
    EXEC('ALTER TABLE __TableName__ DROP CONSTRAINT ' + @ConstraintName)
    IF EXISTS (SELECT * FROM syscolumns WHERE id=object_id('__TableName__') AND name='__ColumnName__')
    EXEC('ALTER TABLE __TableName__ DROP COLUMN __ColumnName__')
    

    只需将 TableNameColumnName 替换为适当的值。即使列已被删除,您也可以安全地运行它。

    奖励:这是删除外键和其他类型约束的代码。

    IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where TABLE_NAME = '__TableName__' AND COLUMN_NAME = '__ColumnName__')
    BEGIN
    SELECT @ConstraintName = CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where TABLE_NAME = '__TableName__' AND COLUMN_NAME = '__ColumnName__'
    EXEC('ALTER TABLE __TableName__ DROP CONSTRAINT ' + @ConstraintName)
    END
    

    Blog

    【讨论】:

    • 现在两次救了我的命。他们两个,都必须删除检查约束。首先,我必须使用第一个查询。其次,我必须使用第二个查询,因为在 SYS.DEFAULT_CONSTRAINTS 表中找不到检查约束。非常感谢!
    【解决方案6】:

    当我们尝试删除依赖的列时,我们会看到这种错误:

    对象 'DF__*' 依赖于列 ''。

    删除依赖于该列的约束:

    ALTER TABLE TableName DROP CONSTRAINT dependent_constraint;
    

    示例:

    消息 5074,第 16 级,状态 1,第 1 行

    对象 'DF__Employees__Colf__1273C1CD' 依赖于列 'Colf'。

    消息 4922,第 16 级,状态 9,第 1 行

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

    删除约束(DF__Employees__Colf__1273C1CD):

    ALTER TABLE Employees DROP CONSTRAINT DF__Employees__Colf__1273C1CD;
    

    然后就可以Drop Column了:

    Alter Table TableName Drop column ColumnName
    

    【讨论】:

      【解决方案7】:

      解决办法:

      打开数据库表->展开表->展开约束看看这个

      【讨论】:

      • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
      【解决方案8】:

      我在尝试运行迁移时遇到此错误 为了解决这个问题,我重命名了该列并使用

      重新生成了迁移
      add-migration migrationname -force
      

      在包管理器控制台中。然后我就可以运行了

      update-database
      

      成功了。

      【讨论】:

      • 小心,这不会重命名列 - 它会删除列并添加新列。除非您在迁移中添加自定义代码,否则您将丢失该列中曾经存在的所有数据。
      【解决方案9】:

      从多个表中删除列时,我遇到了以下默认约束错误。如果您需要更改列的数据类型,则会出现类似的问题。

      对象“DF_TableName_ColumnName”依赖于列“ColumnName”。

      要解决这个问题,我必须首先使用以下查询删除所有这些约束

      DECLARE @sql NVARCHAR(max)=''     
      SELECT @SQL += 'Alter table ' + Quotename(tbl.name) + '  DROP constraint ' + Quotename(cons.name) + ';'
       FROM SYS.DEFAULT_CONSTRAINTS cons 
       JOIN   SYS.COLUMNS col ON col.default_object_id = cons.object_id
       JOIN   SYS.TABLES tbl ON tbl.object_id = col.object_id
       WHERE  col.[name] IN ('Column1','Column2')
      
      --PRINT @sql
      EXEC Sp_executesql @sql 
      

      之后,我删除了所有这些列(我的要求,此问题中未提及)

      DECLARE @sql NVARCHAR(max)='' 
      SELECT @SQL += 'Alter table ' + Quotename(table_catalog)+ '.' + Quotename(table_schema) + '.'+ Quotename(TABLE_NAME) 
                     + '  DROP column ' + Quotename(column_name) + ';'
      FROM   information_schema.columns where COLUMN_NAME IN ('Column1','Column2')  
      --PRINT @sql
      EXEC Sp_executesql @sql 
      

      我在这里发帖以防有人发现同样的问题。

      编码愉快!

      【讨论】:

      • 这段代码在哪里放弃约束?它会丢弃列,而且相当危险。另外,请注意this answer 已经展示了一种生成所需 SQL 的方法。
      • @GertArnold 您提到的答案是针对特定表的,而我的脚本是针对具有相似列名的多个表的。另外,我修改了答案并添加了约束部分。感谢提及。
      猜你喜欢
      • 2012-05-06
      • 2014-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-11
      相关资源
      最近更新 更多