无法启用约束。一行或多行包含违反非空、唯一或外键约束的值

Posted

技术标签:

【中文标题】无法启用约束。一行或多行包含违反非空、唯一或外键约束的值【英文标题】:Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints 【发布时间】:2011-10-24 23:44:54 【问题描述】:

我在informix 数据库中进行了外连接并成功执行,但我的代码中出现以下异常:

DataTable dt = TeachingLoadDAL.GetCoursesWithEvalState(i, bat);

未能启用约束。一行或多行包含值 违反非空、唯一或外键约束。

我知道问题所在,但我不知道如何解决。

我进行外连接的第二个表包含一个复合主键,在上一个外连接查询中为空。

编辑:

    SELECT UNIQUE a.crs_e,  a.crs_e  || '/ ' || a.crst crs_name, b.period,
           b.crscls, c.crsday, c.from_lect, c.to_lect,
           c.to_lect - c.from_lect + 1 Subtraction, c.lect_kind, e.eval, e.batch_no,
           e.crsnum, e.lect_code, e.prof_course
    FROM rlm1course a, rfc14crsgrp b, ckj1table c, mnltablelectev d,
         OUTER(cc1assiscrseval e)  
    WHERE a.crsnum = b.crsnum 
    AND b.crsnum = c.crsnum 
    AND b.crscls = c.crscls 
    AND b.batch_no = c.batch_no 
    AND c.serial_key = d.serial_key  
    AND c.crsnum = e.crsnum  
    AND c.batch_no = e.batch_no  
    AND d.lect_code= e.lect_code 
    AND d.lect_code = .... 
    AND b.batch_no = ....

问题发生在表cc1assiscrseval。主键是(batch_no, crsnum, lect_code)。

如何解决这个问题?


编辑:

根据@PaulStock的建议: 我照他说的做,我得到:

? dt.GetErrors()[0] System.Data.DataRow HasErrors: true ItemArray: object[10] RowError:“列 'eval' 不允许 DBNull.Value。”

所以我通过将 e.eval 替换为 ,NVL (e.eval,'') eval 来解决我的问题。这解决了我的问题。 非常感谢。

【问题讨论】:

当我从查询中删除 ,e.eval,e.batch_no,e.crsnum,e.lect_code,e.prof_course 时,一切正常。请问有什么问题。 ADO.NET 中还有一个错误,其中“非唯一聚集索引”会在 DataTable 上创建错误的 Data.UniqueConstraint 项。 【参考方案1】:

此问题通常由以下原因之一引起

为未设置为 AllowDBNull 的列返回空值 使用相同的主键返回重复的行。 数据库和数据集之间的列定义不匹配(例如 char 字段的大小)

如果结果集不是太大,请尝试以本机方式运行查询并查看结果。如果您已经消除了空值,那么我的猜测是主键列被重复了。

或者,要查看确切的错误,您可以像这样手动将 Try/Catch 块添加到生成的代码中,然后在引发异常时中断:

然后在命令窗口中,在得到错误的表上调用GetErrors 方法。 对于 C#,命令为 ? dataTable.GetErrors() 对于VB,命令是? dataTable.GetErrors

这将显示所有有错误的数据行。然后,您可以查看其中每个的RowError,它应该会告诉您无效的列以及问题。因此,要查看错误第一个数据行的错误,命令是:? dataTable.GetErrors(0).RowError 或在 C# 中为 ? dataTable.GetErrors()[0].RowError

【讨论】:

非常感谢。 >? dt.GetErrors()[0] System.Data.DataRow HasErrors: true ItemArray: object[10] RowError: "Column 'eval' does not allow DBNull.Value." 太棒了。那不起作用,但我可以为数据集添加一个监视并在其后键入 .GetErrors 并扩展值。这是非常有用的。希望下次我需要它之前我不会忘记它:) 是的,这真的很有帮助——我出错的原因是字段的长度比表适配器中列的 maxLength 长。我确实注意到的一件事是,为了在设计器文件中命中断点,您需要转到工具 > 选项 > 调试,并确保未选中“仅启用我的代码”。然后它将允许您逐步完成设计器文件代码。 感谢@PaulStock 的回答我解决了同样的问题。 这非常有用,我发现数据列长度不匹配 - 它在数据库中而不是在数据集中增加。【参考方案2】:

您可以禁用数据集上的约束。它将允许您识别不良数据并帮助解决问题。

例如

dataset.TableA.Clear();
dataset.EnforceConstraints = false;
dataAdapter1.daTableA.Fill(dataset, TableA");

您的填充方法可能略有不同。

【讨论】:

这帮助我找到了导致我的问题的数据,这不是“错误数据”,而是数据源配置向导的不良行为。它显然没有得到修改的列约束(而且我错过了一个添加的表来启动),尽管出去和数据库交谈......并且没有启用缓存。 感谢您的回答。我有一个区分大小写的问题,只需要在数据集中适当地设置它。【参考方案3】:

这将查找表中所有有错误的行,打印出该行的主键以及该行发生的错误...

这是在 C# 中,但将其转换为 VB 应该不难。

 foreach (DataRow dr in dataTable)
 
   if (dr.HasErrors)
     
        Debug.Write("Row ");
        foreach (DataColumn dc in dataTable.PKColumns)
          Debug.Write(dc.ColumnName + ": '" + dr.ItemArray[dc.Ordinal] + "', ");
        Debug.WriteLine(" has error: " + dr.RowError);
     
  

糟糕——抱歉,PKColumns 是我在扩展 DataTable 时添加的,它告诉我构成 DataTable 主键的所有列。如果您知道数据表中的主键列,则可以在此处遍历它们。就我而言,由于我所有的数据表都知道它们的 PK cols,因此我可以为所有表自动编写这些错误的调试。

输出如下:

Row FIRST_NAME: 'HOMER', LAST_NAME: 'SIMPSON', MIDDLE_NAME: 'J',  has error: Column 'HAIR_COLOR' does not allow DBNull.Value.

如果您对上面的 PKColumns 部分感到困惑 - 这会打印出列名和值,这不是必需的,但会添加有用的故障排除信息,以识别可能导致问题的列值。删除此部分并保留其余部分仍将打印正在生成的 SQLite 错误,这将记录有问题的列。

【讨论】:

找出问题所在的绝妙方法。在我继承的与数据不一致的解决方案中,完全帮助我解决了问题。虽然它在 DataSet 上,但我只是遍历每个表,然后是每一行。如果可以的话 +10。 这对我有用。这是一个Column 'MyColumn' does not allow DBNull.Value,但它不会以任何其他方式显示。谢谢:)【参考方案4】:

确保表适配器查询中指定的字段与您定义的查询中的字段匹配。 DAL 似乎不喜欢不匹配。在将新字段添加到表后,这通常会发生在您的存储过程和查询上。

如果你在数据库中修改了varchar字段的长度,而XSS文件中包含的XML没有拾取,在XML中找到字段名和属性定义,手动修改。

如果主键与返回的数据无关,则从表适配器的选择列表中删除它们。

在 SQL Management Studio 中运行查询并确保没有返回重复记录。重复记录会生成重复的主键,这将导致此错误。

SQL 联合可能会造成麻烦。我修改了一个表格适配器,在其他表格之前添加了一条“请选择员工”记录。对于其他字段,我提供了虚拟数据,例如长度为 1 的字符串。 DAL 从该初始记录中推断出架构。后面带有长度为 12 的字符串的记录失败。

【讨论】:

欢迎来到 SO,鲍勃。我已经编辑了您的答案(尽管仍在审查中)。例如,我们不希望在答案中包含问候语和签名(这被认为是“噪音”,请参阅常见问题解答)。无论如何,您的姓名和头像将始终显示在答案下方。【参考方案5】:

这对我有用,来源:here

我遇到了这个错误,它与数据库约束无关(至少在我的情况下)。我有一个带有 GetRecord 查询的 .xsd 文件,该查询返回一组记录。该表的其中一列是“nvarchar(512)”,在项目的中间,我需要将其更改为“nvarchar(MAX)”。

一切正常,直到用户在该字段中输入超过 512 并且我们开始收到著名的错误消息“无法启用约束。一行或多行包含违反非空、唯一或外键约束的值。 "

解决方案:检查 DataTable 中列的所有 MaxLength 属性。

我从“nvarchar(512)”更改为“nvarchar(MAX)”的列的 MaxLength 属性仍然具有 512 值,因此我更改为“-1”并且它有效!!。

【讨论】:

我的问题也一定是 MaxLength。我使用 VWD 2010 数据集设计器。源表已被其他人更改。我将 SQL Query 修改为 select *,认为这会刷新所有列,但显然它没有更新现有长度。所以我修改了查询以选择一个字段,保存 .xsd,在 Notepad++ 中打开 .xsd 以检查除了一个 MaxLength defs 之外的所有内容,然后再次将查询修改为select *。这刷新了 MaxLengths 并让我克服了这个错误。 非常感谢,我一整天都在摸索这个问题,因为一切都很好。我还必须更改为 nvarchar(MAX),但 DataTable 将 MaxLength 保持在 10!我欠你一杯!【参考方案6】:

问题出在数据访问设计器上。在 Visual Studio 中,当我们将视图从“服务器资源管理器”拉到设计器窗口时,它会在列上随机添加主键或将某些内容标记为 NOT NULL,尽管它实际上设置为 null。尽管在 SQL 数据库服务器中实际创建视图,没有定义任何主键或定义 NOT NULL,但 VS 设计器正在添加此键/约束。

您可以在设计器中看到这一点 - 它在列名称的左侧显示为一个钥匙图标。

解决方案:右键单击钥匙图标并选择“删除钥匙”。这应该可以解决问题。您还可以右键单击列并选择“属性”以在 VS 数据访问设计器中查看列的属性列表并适当更改值。

【讨论】:

【参考方案7】:

这个错误也出现在我的项目中。我尝试了此处发布的所有建议解决方案,但完全没有运气,因为问题与字段大小、表键字段定义、约束或 EnforceConstraints 数据集变量无关。

在我的例子中,我还有一个 .xsd 对象,我在项目设计期间(数据访问层)将它放在那里。当您将数据库表对象拖到 Dataset 可视项中时,它会从底层数据库中读取每个表定义,并将约束复制到 Dataset 对象中,这与您在数据库中创建表时所定义的完全相同(SQL Server 2008 R2 in my案子)。这意味着使用“非空”或“外键”约束创建的每个表列也必须出现在 SQL 语句或存储过程的结果中。

在我将所有关键列和定义为“非空”的列包含到我的查询中后,问题就完全消失了。

【讨论】:

【参考方案8】:

当我在 xsd 文件中的数据表的日期字段上将 AllowDBNull 设置为 True 时,我的开始工作了。

【讨论】:

【参考方案9】:

听起来可能有一个或多个列被选择:

   e.eval, e.batch_no, e.crsnum, e.lect_code, e.prof_course

在您的数据集定义中将 AllowDBNull 设置为 False

【讨论】:

我为该表中的所有列设置了 allow null = true 但徒劳无功。【参考方案10】:

目前尚不清楚为什么运行 SELECT 语句应该涉及启用约束。我不知道 C# 或相关技术,但我知道 Informix 数据库。如果您的查询代码启用(并且可能还禁用)约束,系统会出现一些奇怪的情况。

您还应该避免使用老式的、非标准的 Informix OUTER 连接表示法。除非您使用的是非常旧的 Informix 版本,否则您应该使用 SQL-92 样式的连接。

您的问题似乎提到了两个外连接,但您在示例查询中只显示了一个。这也有点令人费解。

'e'与其余表的连接条件为:

AND c.crsnum = e.crsnum  
AND c.batch_no = e.batch_no  
AND d.lect_code= e.lect_code 

这是一个不寻常的组合。由于我们没有具有相关参照完整性约束的架构的相关子集,因此很难知道这是否正确,但是像这样在 3 个表之间连接有点不寻常。

这些都不是您问题的明确答案;但是,它可能会提供一些指导。

【讨论】:

【参考方案11】:

感谢您迄今为止的所有投入。我只是想补充一点,虽然一个人可能已经成功地规范了数据库,更新了他们的应用程序的任何模式更改(例如数据集)等等,还有另一个原因:sql CARTESIAN 产品(在查询中加入表时)。

笛卡尔查询结果的存在会导致连接两个或多个表的主(或键优先)表中的重复记录。 即使您在 SQL 中指定了“Where”子句,如果 JOIN with secondary table 例如包含不等连接(在从 2 个或多个 UNrelated 表中获取数据时很有用),则仍可能出现笛卡尔:

FROM tbFirst INNER JOIN tbSystem ON tbFirst.reference_str tbSystem.systemKey_str

解决方案: 表应该是相关的。

谢谢。查格伯特

【讨论】:

【参考方案12】:

我通过将它从 false 更改为 true 解决了同样的问题。最后我进入数据库并将我的位字段更改为允许null,然后刷新我的xsd,刷新我的wsdl和reference.cs,现在一切都很好。

this.columnAttachPDFToEmailFlag.AllowDBNull = true;

【讨论】:

【参考方案13】:

简单的解决方案:

转到 MSSQL Studio 服务器;

运行此错误原因的查询:在我的情况下,我看到 id 值为 null,因为我忘记将 身份规范增量设置为 1。

因此在 id 字段中输入 1,因为它是自动递增的,并且在设计视图中修改不允许 NULLS

这是导致我的 bindingsource 和 tabel adapter throwin 错误的错误:

   this.exchangeCheckoutReportTableAdapter.Fill(this.sbmsDataSet.ExchangeCheckouReportTable);

【讨论】:

【参考方案14】:

DirectCast(dt.Rows(0),DataRow).RowError

这直接给出了错误

【讨论】:

好建议,但只有当它是数据表中的第一行有错误时才有效,不是吗?如果返回 100 个好行,然后返回 1 个坏行,Rows(0) 上不会有 RowError,会吗?【参考方案15】:

如果您使用 Visual Studio 数据集设计器获取数据表,并且它会引发错误“无法启用约束”。我遇到了同样的问题,尝试从数据集设计器本身预览数据并将其与数据库中的表匹配。

解决此问题的最佳方法是删除表适配器并创建一个新适配器。

【讨论】:

【参考方案16】:

* 次要方式:*


如果您不需要 [id] 作为主键,

移除其主键属性:

在您的 DataSet > TableAdapter > 右键单击​​ [id] 列 > 选择 Delete key ...

问题将得到解决。

【讨论】:

【参考方案17】:

我也遇到了这个问题,在修改 *.xsd 以反映底层 SQL 服务器中更改的列的修改大小后解决了。

【讨论】:

【参考方案18】:

为了修复这个错误,我从数据集设计器中取下了麻烦的表适配器,并保存了数据集,然后从服务器资源管理器中拖动了一个新的表适配器副本并修复了它

【讨论】:

【参考方案19】:

我通过使用 XML 阅读器打开 .xsd 文件并删除放置在我的一个视图上的约束解决了这个问题。无论出于何种原因,当我将视图添加到数据中时,它在不应该存在的列中添加了主键约束。

另一种方法是正常打开 .xsd 文件,查看导致问题的表/视图并删除任何不应该存在的键(右键单击列,选择 delete key)。

【讨论】:

【参考方案20】:

只是想为上面列出的例外添加另一个可能的原因(特别是对于喜欢手动定义数据集架构的人):

当您的数据集中有两个表并且存在从第一个表的字段 (chfield) 到第二个表的字段 (pfield) 定义的关系 (DataSet.Reletions.Add()) 时,就像添加了一个隐式约束将该字段设为唯一,即使它可能未在您的定义中明确指定为唯一性或主键。

因此,如果您在该父字段 (pfield) 中有重复值的行,您也会遇到此异常。

【讨论】:

【参考方案21】:
            using (var tbl = new DataTable())
            using (var rdr = cmd.ExecuteReader())
            
                tbl.BeginLoadData();

                try
                
                    tbl.Load(rdr);
                
                catch (ConstraintException ex)
                
                    rdr.Close();
                    tbl.Clear();

                    // clear constraints, source of exceptions
                    // note: column schema already loaded!
                    tbl.Constraints.Clear();
                    tbl.Load(cmd.ExecuteReader());
                
                finally
                
                    tbl.EndLoadData();
                
            

【讨论】:

【参考方案22】:

我收到了相同的错误类型,在我的情况下,它通过删除选择字段并用 * 替换它们来解决它。不知道为什么会这样。查询没有错别字或任何花哨的东西。

不是最好的解决方案,但没有其他方法,我已经筋疲力尽了。

在寻找明确答案的过程中,我发现了这个: https://www.codeproject.com/questions/45516/failed-to-enable-constraints-one-or-more-rows-cont

解决方案 8

这个错误也出现在我的项目中,使用 Visual Studio 2010。我尝试了其他博客中发布的其他解决方案,但完全没有运气,因为该问题与字段大小、表键字段定义、约束或EnforceConstraints 数据集变量。

在我的例子中,我有一个 .xsd 对象,我在项目设计期间(在数据访问层中)放置了它。当您将数据库表对象拖到 Dataset 可视项中时,它会从底层数据库中读取每个表定义并将约束复制到 Dataset 对象中,这与您在数据库中创建表时所定义的完全相同(SQL Server 2008 R2在我的情况下)。这意味着使用“非空”或“外键”约束创建的每个表列也必须出现在 SQL 语句或存储过程的结果中。

在我的查询中包含所有受约束的列(非空、主键、外键等)后,问题就完全消失了。

也许您不需要所有表列都出现在查询/存储过程结果中,但是由于仍然应用了约束,因此如果某些受约束的列未出现在结果中,则会显示错误。

希望这对其他人有所帮助。

【讨论】:

【参考方案23】:

在我的例子中,这个错误是由一个字符串列的大小引起的。奇怪的是,当我在不同的工具中执行完全相同的查询时,不存在重复值或空值。

然后我发现字符串列大小的大小是 50,所以当我调用填充方法时,值被截断了,抛出了这个异常。 我单击该列并在属性中将大小设置为 200,错误就消失了。

希望有帮助

【讨论】:

【参考方案24】:

我通过像这样的“子选择”解决了这个问题:

string newQuery = "select * from (" + query + ") as temp";

mysql 上执行时,所有 collunms 属性(唯一、非 null ...)将被清除。

【讨论】:

以上是关于无法启用约束。一行或多行包含违反非空、唯一或外键约束的值的主要内容,如果未能解决你的问题,请参考以下文章

主键约束

MySQL约束 主键约束丨唯一约束丨非空约束丨外键级联

ORA-02292违反完整约束和ORA-02297无法禁用约束条件 cascade禁用主键

Laravel 迁移 - 违反完整性约束:1452 无法添加或更新子行:外键约束失败

创建表时约束

Laravel 6:违反完整性约束:1452无法添加或更新子行:外键约束失败