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

问题描述 投票:152回答:22

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

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

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

我知道这个问题,但我不知道如何解决它。

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

编辑:

    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:“Column'eval'不允许DBNull.Value。”

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

c# asp.net sql database informix
22个回答
320
投票

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

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

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

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

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

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


2
投票

目前尚不清楚为什么运行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个表之间进行连接有点不寻常。

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


2
投票

感谢您到目前为止所做的所有输入。我只是想添加一个,虽然可能已成功规范化数据库,更新其应用程序的任何架构更改(例如更新到数据集)左右,还有另一个原因:sql CARTESIAN产品(在查询中连接表时)。

笛卡尔查询结果的存在将导致正在连接的两个或多个表的主(或键第一)表中的重复记录。即使在SQL中指定了“Where”子句,如果带有辅助表的JOIN包含不等连接(在从2个或更多不相关的表中获取数据时很有用),仍可能出现笛卡尔:

FROM tbFirst INNER JOIN tbSystem on tbFirst.reference_str <> tbSystem.systemKey_str

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

谢谢。 chagbert


1
投票

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

this.columnAttachPDFToEmailFlag.AllowDBNull = true;

0
投票

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

这直接给出了错误


0
投票

如果您使用visual studio数据集设计器来获取数据表,则会抛出错误“无法启用约束”。我遇到了同样的问题,尝试从数据集设计器本身预览数据,并将其与数据库中的表进行匹配。

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


0
投票

*次要方式:*


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

删除其主键属性:

在您的DataSet> TableAdapter>右键单击[id]列>选择删除键...

问题将得到解决。


0
投票

我也有这个问题,它在修改* .xsd后解决,以反映在基础SQL服务器中更改的列的修订大小。


0
投票

为了解决这个错误,我从数据集设计器中取出了令人不安的表适配器,并保存了数据集,然后从服务器资源管理器中拖出了表适配器的新副本并修复了它


0
投票

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

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


0
投票

只是想为上面列出的那些添加另一个可能的异常原因(特别是对于那些喜欢手动定义数据集模式的人):

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

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


35
投票

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

EG

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

填充方法可能会略有不同。


0
投票
            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();
                }
            }

-1
投票

在我的情况下,此错误是由字符串列的大小引起的。奇怪的是,当我在不同的工具中执行完全相同的查询时,重复值和空值都不存在。

然后我发现字符串列大小为50,所以当我调用fill方法时,值被切断,抛出此异常。 我点击列并在属性中设置大小为200,错误消失了。

希望这有帮助


-1
投票

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

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

什么时候在mysql上,所有collunms属性(唯一,非null ...)将被清除。


8
投票

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

这是在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列,我可以自动为所有表编写这些错误的调试。

输出如下所示:

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

7
投票
  • 确保表适配器查询中指定的字段与您定义的查询中的字段匹配。 DAL似乎不喜欢不匹配。在向表中添加新字段后,通常会对您的sprocs和查询进行此操作。
  • 如果更改了数据库中varchar字段的长度,并且XSS文件中包含的XML尚未提取,请在XML中查找字段名称和属性定义并手动更改。
  • 如果表适配器中的主键与返回的数据无关,则从表适配器中的选择列表中删除主键。
  • 在SQL Management Studio中运行查询,并确保没有返回重复的记录。重复记录可能会生成重复的主键,从而导致此错误。
  • SQL联盟可以拼出麻烦。我通过在其他人之前添加“请选择员工”记录来修改一个表适配器。对于其他字段,我提供了虚拟数据,包括例如长度为1的字符串。 DAL从该初始记录推断出模式。记录以下长度为12的字符串失败。

5
投票

这对我有用,来源:here

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

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

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

我从“nvarchar(512)”更改为“nvarchar(MAX)”的列在MaxLength属性上仍然具有512值,因此我更改为“-1”并且它正常工作!!


4
投票

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

您可以在设计器中看到它 - 它在列名称左侧显示一个键图标。

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


3
投票

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

在我的情况下,我还有一个.xsd对象,我在项目设计时(数据访问层)放在那里。当您将数据库表对象拖到数据集可视项中时,它会从基础数据库中读取每个表定义,并将约束复制到数据集对象中,就像在数据库中创建表时一样(在我的SQL Server 2008 R2中)案件)。这意味着使用“not null”或“foreign key”约束创建的每个表列也必须存在于SQL语句或存储过程的结果中。

在我将所有键列和定义为“not null”的列包含在我的查询中之后,问题完全消失了。


3
投票

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


2
投票

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.