SQL数据库中的约束
我需要在T-SQL中有一个表,它的结构如下SQL数据库中的约束,sql,sql-server-2005,tsql,check-constraints,Sql,Sql Server 2005,Tsql,Check Constraints,我需要在T-SQL中有一个表,它的结构如下 KEY Various_Columns Flag 1 row 1 F 2 row_2 F 3 row_3 T 4 row_4 F 要么没有行,要么最多有一行的Flag列的值为T。我的开发人员声称,这可以通过在表上放置check约束来实现 问题: 这样
KEY Various_Columns Flag
1 row 1 F
2 row_2 F
3 row_3 T
4 row_4 F
要么没有行,要么最多有一行的Flag列的值为T。我的开发人员声称,这可以通过在表上放置check约束来实现
问题:
1个。每行有一个检查约束。没有其他约束也会这样做 您需要一个:
- 触发器(所有版本)
- 具有筛选器标志=T和唯一索引打开标志(SQL Server 2000+)的索引视图
- 筛选索引(SQL Server 2008)
CHECK
约束中的子查询(这是完整SQL-92的要求;从广义上讲,SQL Server仅符合入门级SQL-92)
虽然在SQL Server中几乎肯定有更好的强制执行此约束的方法,但纯粹出于兴趣,确实可以使用行级别的检查约束和唯一的约束来实现此约束,例如,这里有一种方法:
CREATE TABLE YourStuff
(
key_col INTEGER NOT NULL UNIQUE,
Various_Columns VARCHAR(8) NOT NULL,
Flag CHAR(1) DEFAULT 'F' NOT NULL
CHECK (Flag IN ('F', 'T')),
Flag_key INTEGER UNIQUE,
CHECK (
(Flag = 'F' AND Flag_key = key_col)
OR
(Flag = 'T' AND Flag_key = NULL)
)
);
这里的问题是,您需要“手动”维护标志键
列的值。用计算列替换列+检查
,意味着值将自动保持:
CREATE TABLE YourStuff
(
key_col INTEGER NOT NULL UNIQUE,
Various_Columns VARCHAR(8) NOT NULL,
Flag CHAR(1) DEFAULT 'F' NOT NULL
CHECK (Flag IN ('F', 'T')),
Flag_key AS (
CASE WHEN Flag = 'F' THEN key_col
ELSE NULL END
),
UNIQUE (Flag_key)
);
**虽然SQL Server不直接支持检查约束中的子查询,但在某些情况下,可以使用用户定义函数(UDF)来解决此问题,例如
请注意,UDF方法不会在所有情况下都有效,需要谨慎。重要的一点是,UDF将针对每个受影响的行进行评估(而不是像您所期望的那样,在SQL语句或事务级别)。在这种情况下,每个受影响的行的约束都必须为真,因此——我认为!——它是安全的。有关更多详细信息,请参阅
就个人而言,我只需要使用第二个表来建模标志
,它只涉及键和外键,例如
CREATE TABLE YourStuff
(
key_col INTEGER NOT NULL UNIQUE,
Various_Columns VARCHAR(8) NOT NULL
);
CREATE TABLE YourStuffFlag
(
key_col INTEGER NOT NULL UNIQUE
REFERENCES YourStuff (key_col)
);
[我的]桌子是正常的吗
你应该瞄准第五范式(5NF)。这取决于各种列的设计。我不认为您的标志
符合5NF的要求,我也没有看到任何更新、删除或插入异常(这是标准化的要点,但5NF设计仍可能显示异常)。也就是说,要切换获取标志的行
attibute,我的双表设计需要一条UPDATE
语句,而您的单表设计需要两条;) 请选择哪个版本的SQL Server?目前,Microsoft SQL Server 2005只是为了防止这是一个“问题”的“答案”列表,您可以将正确答案和问题以及所有错误答案保存在一个表中。单个不重复的真实答案与问题的主键直接相关。我想我会提到,因为模式看起来很熟悉。每一行对应一个不同的“人”,根据不同的规则分配“某物”。一个绝对的规则是,被分配的东西不能连续两次给同一个人。“标志”表示最后一个人。在SQL Server 2008中筛选索引之前,可以使用带有复选选项的使用单独的视图,并要求用户通过视图而不是基表进行更新。虽然不太理想,但这表明通常有很多方法可以剥猫皮(更多方法请参见我的答案)。注意诸如“你需要一个”之类的短语感谢您的输入和使用unique的巧妙解决方案,在“适当的标志字段”旁边使用“数字标志字段”。我对所有解决方案的偏好是使用第二个包含我标志行索引的表。
CREATE TABLE YourStuff
(
key_col INTEGER NOT NULL UNIQUE,
Various_Columns VARCHAR(8) NOT NULL
);
CREATE TABLE YourStuffFlag
(
key_col INTEGER NOT NULL UNIQUE
REFERENCES YourStuff (key_col)
);