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

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

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

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

我知道这个问题,但我不知道如何修复它 .

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

EDIT:

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) .

如何解决这个问题?


EDIT:

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

? dt.GetErrors()[0] HasErrors:true ItemArray:{object [10]} RowError:“Column'eval'不允许DBNull.Value . ”

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

回答(22)

2 years ago

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

对于未设置为AllowDBNull的列,将返回

  • null值
    使用相同的主键返回

  • 个重复行 .

  • 数据库和数据集之间的列定义(例如字段的大小)不匹配

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

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

enter image description here

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

enter image description here

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

enter image description here

2 years ago

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

例如

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

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

2 years ago

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

这是在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.

2 years ago

  • 确保表适配器查询中指定的字段与您定义的查询中的字段匹配 . DAL似乎不喜欢不匹配 . 在向表中添加新字段后,通常会对您的sprocs和查询进行此操作 .

  • 如果您更改了数据库中varchar字段的长度,并且XSS文件中包含的XML未提取它,请在XML中查找字段名称和属性定义并手动更改 .

  • 从表适配器中的选择列表中删除主键(如果它们与返回的数据无关) .

  • 在SQL Management Studio中运行查询,确保没有返回重复的记录 . 重复记录可能会生成重复的主键,从而导致此错误 .

  • SQL联盟可以拼出麻烦 . 我通过在其他人之前添加“请选择员工”记录来修改一个表适配器 . 对于其他字段,我提供了虚拟数据,包括例如长度为1的字符串 . DAL从该初始记录推断出模式 . 记录以下长度为12的字符串失败 .

2 years ago

这对我有用,来源:here

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

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

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

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

2 years ago

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

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

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

2 years ago

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

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

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

2 years ago

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

2 years ago

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

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

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

2 years ago

目前尚不清楚为什么运行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 years ago

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

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

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

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

谢谢 . chagbert

2 years ago

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

this.columnAttachPDFToEmailFlag.AllowDBNull = true;

2 years ago

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

这直接给出了错误

2 years ago

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

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

2 years ago

*** Secondary way : ***


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

删除其主键属性:

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

问题将得到解决 .

2 years ago

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

2 years ago

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

2 years ago

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

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

2 years ago

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

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

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

2 years ago

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

2 years ago

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

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

希望这有帮助

2 years ago

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

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

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