唯一性约束问题
环境
Visual Studio 2008 (UNIQUE约束不允许出现重复的NULL值)
SQLite ADO.NET
SQLite 3.1.9.2085 (UNIQUE约束允许出现重复的NULL值)
数据库DBTest.db,表UNIQUE_TEST
1 CREATE TABLE [UNIQUE_TEST] ( 2 [ID] INTEGER PRIMARY KEY, 3 [SNO] INTEGER NULL, 4 CONSTRAINT [UNIQUE_ID] UNIQUE([SNO]) 5 );
在Visual Studio 2008的项目中新建一个包含如下清单的窗体
控件 |
名称 |
备注 |
DataGridView |
dataGridView1 |
用于显示数据库中的数据 |
Button |
btnFill |
用于从数据库填充数据到DataGridView |
Button |
btnUpdate |
用于将变更更新到数据源 |
把DBTest.db作为数据源添加到项目,在自动生成的数据集文件UNIQUE_TEST.xsd中,找到关于约束的定义,如下
1 <xs:unique name=”Constraint1” msdata:PrimaryKey=”true”> 2 <xs:selector xpath=”.//mstns:UNIQUE_TEST” /> 3 <xs:field xpath=”mstns:ID” /> 4 </xs:unique>
上述自动生成的代码中并无与[UNIQUE_TEST].[SNO]列对应的UNIQUE约束。
自定义工具生成的代码对应的文件UNIQUE_TEST.Designer.cs中,找到关于约束的定义,如下
1 this.Constraints.Add(new 2 Global::System.Data.UniqueConstraint(“Constraint1”, 3 new Global::System.Data.DataColumn[]{ this.columnID }, true)); 4 this.columnID.AllowDBNull = false; 5 this.columnID.Unique = true;
上述自动生成的代码中并无与[UNIQUE_TEST].[SNO]列对应的UNIQUE约束。
以上是Visual Studio 2008自动生成的代码,在未修改前可正常通过Adapter.Fill()方法填充数据。
但这与要求不符。
要求:SNO列不能重复(可以不填留空)。
此时只在数据库端有约束控制,应用程序端可以在dataGridView1中的SNO列输入重复内容,不会引发DataError事件,但执行Update操作时出现违反约束的异常。
为了在应用端控制输入数据的合法性,手动在数据集文件UNIQUE_TEST.xsd文件中对SNO列添加UNIQUE约束,如下
1 <!— ID IS PRIMARY KEY --> 2 <xs:unique name=”Constraint1” msdata:PrimaryKey=”true”> 3 <xs:selector xpath=”.//mstns:UNIQUE_TEST” /> 4 <xs:field xpath=”mstns:ID” /> 5 </xs:unique> 6 7 <!— SNO IS UNIQUE --> 8 <xs:unique name=”Constraint2” > 9 <xs:selector xpath=”.//mstns:UNIQUE_TEST” /> 10 <xs:field xpath=”mstns:SNO” /> 11 </xs:unique>
在Visual Studio 2008中重新运行自定义工具,生成的UNIQUE_TEST.Designer.cs中,关于约束的定义,如下
1 this.Constraints.Add(new 2 Global::System.Data.UniqueConstraint(“Constraint1”, 3 new Global::System.Data.DataColumn[]{ this.columnID }, true)); 4 this.Constraints.Add(new 5 Global::System.Data.UniqueConstraint(“Constraint2”, 6 new Global::System.Data.DataColumn[]{ 7 this.columnSNO }, false)); 8 this.columnID.AllowDBNull = false; 9 this.columnID.Unique = true; 10 this.columnSNO.Unique = true;
修改后的代码逻辑上与要求相符。
运行,在数据库中SNO列为空,行数超过1行的情况下,在填充时问题出现了:
System.Data.ConstraintException: 未能启用约束。一行或多行中包含违反非空、唯一或外键约束的值。 |
调试状态程序无法继续运行,执行状态程序崩溃。
问题
1. 如何在应用程序段实现要求:SNO列不能重复(可以不填留空)? |
我觉得可以这样来实现:
简单的说,通过触发器在Unique_Test_sno表中插入数据来限制非null的sno列唯一。
Unique列是否允许出现重复的NULL与数据库引擎有关,可以采取计算列等方式解决。
Unique列是否允许出现重复的NULL与数据库引擎有关,可以采取计算列等方式解决。