我在 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
时,一切正常。请问有什么问题。
此问题通常由以下原因之一引起
为未设置为 AllowDBNull 的列返回空值
使用相同的主键返回重复的行。
数据库和数据集之间的列定义(例如 char 字段的大小)不匹配
如果结果集不是太大,请尝试本地运行查询并查看结果。如果您已经消除了空值,那么我的猜测是主键列被复制了。
或者,要查看确切的错误,您可以像这样手动将 Try/Catch 块添加到生成的代码中,然后在引发异常时中断:
https://i.stack.imgur.com/HQrHa.png
然后在命令窗口中,对出现错误的表调用 GetErrors
方法。
对于 C#,命令为 ? dataTable.GetErrors()
对于 VB,命令为 ? dataTable.GetErrors
https://i.stack.imgur.com/ekNb5.png
这将显示所有有错误的数据行。然后,您可以查看其中每个的 RowError
,它应该会告诉您无效的列以及问题。因此,要查看错误中第一个数据行的错误,命令为:
? dataTable.GetErrors(0).RowError
或在 C# 中为 ? dataTable.GetErrors()[0].RowError
https://i.stack.imgur.com/Ynmlf.png
您可以禁用数据集上的约束。它将允许您识别不良数据并帮助解决问题。
例如
dataset.TableA.Clear();
dataset.EnforceConstraints = false;
dataAdapter1.daTableA.Fill(dataset, TableA");
填充方法对您来说可能略有不同。
这将找到表中所有有错误的行,打印出该行的主键和该行发生的错误...
这是在 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 错误,这将记录有问题的列。
Column 'MyColumn' does not allow DBNull.Value
,但它不会以任何其他方式显示。谢谢 :)
确保表适配器查询中命名的字段与您定义的查询中的字段匹配。 DAL 似乎不喜欢不匹配。在将新字段添加到表后,这通常会发生在您的存储过程和查询上。
如果你更改了数据库中某个varchar字段的长度,而XSS文件中包含的XML没有拾取它,请在XML中找到字段名称和属性定义并手动更改。
如果主键与返回的数据无关,则从表适配器中的选择列表中删除它们。
在 SQL Management Studio 中运行查询并确保没有返回重复记录。重复记录会生成重复的主键,这将导致此错误。
SQL 联合会带来麻烦。我修改了一个表格适配器,在其他表格之前添加了“请选择员工”记录。对于其他字段,我提供了虚拟数据,例如长度为 1 的字符串。 DAL 从该初始记录中推断出架构。后面带有长度为 12 的字符串的记录失败。
这对我有用,来源:here
我有这个错误,它与数据库约束无关(至少在我的情况下)。我有一个带有 GetRecord 查询的 .xsd 文件,该查询返回一组记录。该表的一列是“nvarchar(512)”,在项目的中间,我需要将其更改为“nvarchar(MAX)”。
一切正常,直到用户在该字段中输入超过 512 并且我们开始收到著名的错误消息“无法启用约束。一行或多行包含违反非空、唯一或外键约束的值”。
解决方案:检查 DataTable 中列的所有 MaxLength 属性。
我从“nvarchar(512)”更改为“nvarchar(MAX)”的列的 MaxLength 属性仍然具有 512 值,因此我更改为“-1”并且它有效!!。
select *
,认为这会刷新所有列,但显然它没有更新现有长度。所以我修改了查询以选择一个字段,保存 .xsd,在 Notepad++ 中打开 .xsd 以检查除一个 MaxLength defs 之外的所有内容,然后再次将查询修改为 select *
。这刷新了 MaxLengths 并让我克服了这个错误。
问题出在数据访问设计器上。在 Visual Studio 中,当我们将视图从“服务器资源管理器”拉到设计器窗口时,它会在列上随机添加主键或将某些内容标记为 NOT NULL,尽管它实际上设置为 null。尽管 SQL db 服务器中的实际视图创建没有定义任何主键或未定义 NOT NULL,但 VS 设计器正在添加此键/约束。
您可以在设计器中看到这一点 - 它在列名称左侧显示为一个钥匙图标。
解决方案:右键单击密钥图标并选择“删除密钥”。这应该可以解决问题。您还可以右键单击列并选择“属性”以在 VS 数据访问设计器中查看列的属性列表并适当地更改值。
这个错误也出现在我的项目中。我尝试了此处发布的所有建议的解决方案,但完全没有运气,因为问题与字段大小、表键字段定义、约束或 EnforceConstraints 数据集变量无关。
就我而言,我还有一个 .xsd 对象,我在项目设计期间(数据访问层)将其放在那里。当您将数据库表对象拖到 Dataset 可视项中时,它会从底层数据库中读取每个表定义,并将约束复制到 Dataset 对象中,这与您在数据库中创建表时所定义的完全相同(SQL Server 2008 R2 in my案子)。这意味着使用“非空”或“外键”约束创建的每个表列也必须出现在 SQL 语句或存储过程的结果中。
在我的查询中包含所有关键列和定义为“非空”的列后,问题完全消失了。
当我在 xsd 文件中的数据表的日期字段上将 AllowDBNull
设置为 True 时,我的开始工作。
听起来可能有一个或多个列被选择:
e.eval, e.batch_no, e.crsnum, e.lect_code, e.prof_course
在您的数据集定义中将 AllowDBNull 设置为 False。
不清楚为什么运行 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 个表之间连接有点不寻常。
这些都不是您问题的明确答案;但是,它可能会提供一些指导。
感谢您迄今为止所做的所有投入。我只是想补充一点,虽然一个人可能已经成功地规范了数据库,更新了对其应用程序的任何模式更改(例如数据集),但还有另一个原因:sql CARTESIAN 产品(在查询中加入表时)。
笛卡尔查询结果的存在会导致连接两个或多个表的主(或键优先)表中的重复记录。即使您在 SQL 中指定“Where”子句,如果 JOIN with secondary table 例如包含不等连接(在从 2 个或多个 UNrelated 表中获取数据时很有用),则仍可能出现笛卡尔坐标:
FROM tbFirst INNER JOIN tbSystem ON tbFirst.reference_str <> tbSystem.systemKey_str
解决方案:表应该是相关的。
谢谢。查伯特
我通过将其从 false 更改为 true 解决了同样的问题。最后我进入数据库并将我的位字段更改为允许 null,然后刷新我的 xsd,刷新我的 wsdl 和 reference.cs,现在一切都很好。
this.columnAttachPDFToEmailFlag.AllowDBNull = true;
简短而简单的解决方案:
转到 MSSQL Studio 服务器;
运行此错误原因的查询:在我的情况下,我看到 id 值为空,因为我忘记将身份规范增量设置为 1。
https://i.stack.imgur.com/KPmHf.png
因此在 id 字段中输入 1,因为它是自动递增的,并且在设计视图中修改不允许 NULLS
https://i.stack.imgur.com/5kal7.png
那是导致我的 bindingsource 和 tabel 适配器在此代码中抛出错误的错误:
this.exchangeCheckoutReportTableAdapter.Fill(this.sbmsDataSet.ExchangeCheckouReportTable);
DirectCast(dt.Rows(0),DataRow).RowError
这直接给出了错误
Rows(0)
上不会有 RowError
,对吗?
如果您使用 Visual Studio 数据集设计器来获取数据表,并且它会引发错误“无法启用约束”。我遇到了同样的问题,尝试从数据集设计器本身预览数据并将其与数据库中的表匹配。
解决此问题的最佳方法是删除表适配器并创建一个新适配器。
* 次要方式:*
如果您不需要 [id] 作为主键,
删除其主键属性:
在您的 DataSet > TableAdapter > 右键单击 [id] 列 > 选择 Delete key ...
问题将得到解决。
我也遇到了这个问题,在修改 *.xsd 以反映在底层 SQL 服务器中更改的列的修改大小后解决了。
为了解决这个错误,我从数据集设计器中取下了麻烦的表适配器,并保存了数据集,然后从服务器资源管理器中拖动了一个新的表适配器副本并修复了它
我通过使用 XML 阅读器打开 .xsd 文件并删除放置在我的一个视图上的约束解决了这个问题。无论出于何种原因,当我将视图添加到数据时,它在不应该存在的列中添加了主键约束。
另一种方法是正常打开 .xsd 文件,查看导致问题的表/视图并删除任何不应该存在的键(右键单击列,选择 delete key
)。
只想为上面列出的异常添加另一个可能的原因(特别是对于喜欢手动定义数据集模式的人):
当您的数据集中有两个表并且存在从第一个表的字段 (chfield
) 到第二个表的字段 (pfield
) 定义的关系 (DataSet.Reletions.Add()
) 时,就像向该字段添加了一个隐式约束是unique,即使它可能没有在您的定义中明确指定,既不是唯一也不是主键。
因此,如果您在该父字段 (pfield
) 中有具有重复值的行,您也会遇到此异常。
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();
}
}
我收到了相同的错误类型,在我的情况下,它通过删除选择字段并用 * 替换它们来解决它。不知道为什么会这样。该查询没有错别字或任何花哨的东西。
不是最好的解决方案,但没有其他工作,我已经筋疲力尽了。
在寻找明确答案时,我发现了这个: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 语句或存储过程的结果中。
在我的查询中包含所有受约束的列(非空、主键、外键等)后,问题完全消失了。
也许您不需要所有表列都出现在查询/存储过程结果中,但是由于仍然应用了约束,因此如果某些受约束的列未出现在结果中,则会显示错误。
希望这对其他人有帮助。
在我的情况下,这个错误是由字符串列的大小引起的。奇怪的是,当我在不同的工具中执行完全相同的查询时,不存在重复值或空值。
然后我发现字符串列大小的大小是 50,所以当我调用填充方法时,值被截断了,抛出了这个异常。我单击该列并在属性中将大小设置为 200 并且错误消失了。
希望这有帮助
我通过执行“子选择”解决了这个问题:
string newQuery = "select * from (" + query + ") as temp";
在 mysql 上执行此操作时,将清除所有 collunms 属性(唯一、非空 ...)。
>? dt.GetErrors()[0] {System.Data.DataRow} HasErrors: true ItemArray: {object[10]} RowError: "Column 'eval' does not allow DBNull.Value."