Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL数据库中的约束_Sql_Sql Server 2005_Tsql_Check Constraints - Fatal编程技术网

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约束来实现 问题: 这样

我需要在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约束来实现

问题:

  • 这样的约束是否可以在数据库级别放在数据库本身(即行间约束)上,而不是放在用于更新或插入行的业务规则中
  • 这样的桌子是正常的吗
  • 或者,正常形式是否需要删除标志列,而(比如)有另一个简单的表或变量,其中包含标志为T的行的值,即在上述情况下为row=3

  • 1个。每行有一个检查约束。没有其他约束也会这样做

    您需要一个:

    • 触发器(所有版本)
    • 具有筛选器标志=T和唯一索引打开标志(SQL Server 2000+)的索引视图
    • 筛选索引(SQL Server 2008)
    2够了

    真是太过分了。您正在将相同的数据拆分,以避免出现上述解决方案之一。但是使用一个单行表,对ID列使用FK,对Flag使用唯一的约束

    我的开发者声称这可以 通过检查约束实现 放在桌子上

    SQL Server不直接**支持
    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)
    );