SQL 数据库中的约束
我需要在 T-SQL 中有一个表,该表将具有以下结构:
KEY Various_Columns Flag
1 row 1 F
2 row_2 F
3 row_3 T
4 row_4 F
要么没有行,要么最多一行可以具有值为 T 的 Flag 列。我的开发人员声称这可以通过检查约束来实现放在桌子上。
问题:
- 是否可以在数据库级别将这样的约束放在数据库本身上(即行间约束),而不是放在更新或插入行的业务规则中
- 这样的表是否为正常形式?
- 或者正常形式需要删除 Flag 列,取而代之的是(比如说)另一个简单的表或变量,其中包含具有 Flag=T 的行的值,即在上面的情况下 row=3。
I need to have a table in T-SQL which will have the following structure
KEY Various_Columns Flag
1 row 1 F
2 row_2 F
3 row_3 T
4 row_4 F
Either no rows, or at most one row can have the Flag column with the value T. My developer claims that this can be achieved with a check constraint placed on the table.
Questions:
- Can such a constraint be placed on the database itself (ie an inter-row constraint) at the database level, rather than in business rules for updating or inserting rows
- Is such a table in normal form?
- Or would normal form require removing the Flag column, and instead (say) had another simple table or variable containing the value of row which had Flag=T, ie in the above case row=3.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
1 否。检查约束是每行。也没有其他约束可以做到这一点。
您需要以下之一:
2 足够好
3 确实太过分了。您将相同的数据分开以避免上述解决方案之一。但使用单行表、ID 列的 FK 以及 Flag 上的唯一约束
1 No. A check constraint is per row. No other constraint will do this either.
You need one of:
2 Good enough
3 Overkill really. You're splitting the same data up to avoid one the solutions above. But using a one row table, FK for the ID columns, and a unique constraint on Flag
SQL Server 不直接**支持
CHECK
约束中的子查询(这是完整 SQL-92 的要求;一般来说,SQL Server 仅符合入门级 SQL-92)。虽然几乎肯定有更好的方法在 SQL Server 中强制执行此约束,但纯粹出于兴趣,它确实可以使用行级
CHECK
约束和UNIQUE
约束来实现,例如这是一种方法:这里的问题是您需要“手动”维护
Flag_key
列的值。将列 +CHECK
替换为计算列将意味着自动维护值:** 虽然 SQL Server 不直接支持
CHECK
中的子查询约束,在某些情况下有一个使用用户定义函数 (UDF) 的解决方法,例如请注意,UDF 方法并非在所有情况下都有效,因此需要谨慎。重要的一点是,将为受影响的每一行评估 UDF(而不是如您所期望的那样在 SQL 语句或事务级别评估)。在这种情况下,约束对于受影响的每一行都必须成立,因此——我认为! ——很安全。有关更多详细信息,请参阅 CHECK 约束问题作者:大卫·波塔斯。
就我个人而言,我会简单地使用第二个表来建模
Flag
,它只涉及键和外键,例如您应该以第五范式(5NF)为目标。您是否实现了这一点取决于
Various_Columns
的设计。我不认为您的Flag
不符合 5NF 的要求,并且我没有看到任何更新、删除或插入异常(这是规范化的要点,但 5NF 设计仍然可能表现出异常)。也就是说,要切换获取flag
属性的行,我的双表设计需要一个UPDATE
语句,而您的单表设计则需要两个;)SQL Server does not directly** support subqueries in
CHECK
constraints (a requirement for Full SQL-92; SQL Server is only compliant with Entry Level SQL-92, broadly speaking).While there are almost certainly better ways of enforcing this constraint in SQL Server, purely out of interest it can indeed be achieved using a row-level
CHECK
constraint and aUNIQUE
constraint e.g. here's one way:The issue here is that you will need to maintain the
Flag_key
column's values 'manually'. Replacing the column +CHECK
with a calculated column would mean the values are maintained automatically:** While SQL Server does not directly support subqueries in
CHECK
constraints, there is a workaround in some cases using a user defined function (UDF) e.g.Note that the UDF approach won't work in every case and that caution is required. The important point is that UDF will be evaluated for each row affected (rather than at the SQL statement or transaction level, as you may expect). In this case, the constraint needs to be true for every row affected and therefore -- I think! -- it is safe. For more details, see Trouble with CHECK Constraints by David Portas.
Personally, I would simply use a second table to model
Flag
, which would only involve keys and a foreign key e.g.You should by aiming for Fifth normal form (5NF). Whether you have achieved this depends upon the design of
Various_Columns
. I do not believe that yourFlag
falls fowl of the requirements for 5NF and I do not see any update, delete or insert anomalies (which is the point of normalization but a 5NF design can still exhibit anomalies). That said, to switch the row that gets theflag
attibute, my two-table design requires a singleUPDATE
statement while your single-table design requires two ;)