Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.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 Server约束帮助_Sql_Sql Server_Sql Server 2005 - Fatal编程技术网

SQL Server约束帮助

SQL Server约束帮助,sql,sql-server,sql-server-2005,Sql,Sql Server,Sql Server 2005,在SQLServer2005中,我在制定适当的约束方面遇到了问题。我的问题涉及以下表格: Table PKTable { pk integer primary key, property integer, } Table FKTable { pk integer primary key, fk integer references PKTable(pk), } 我真的想让记录fk_rec在它引用的PKTable记录的property=5时不可能存在。我尝试做的第一件事是使用

在SQLServer2005中,我在制定适当的约束方面遇到了问题。我的问题涉及以下表格:

Table PKTable
{
  pk integer primary key,
  property integer,
}

Table FKTable
{
  pk integer primary key,
  fk integer references PKTable(pk), 
}
我真的想让记录fk_rec在它引用的PKTable记录的property=5时不可能存在。我尝试做的第一件事是使用以下查询创建一个绑定到模式的视图,并在UniqueCol字段上创建一个唯一的索引

SELECT     'True' AS UniqueCol, 'uh oh' AS DiffCol
FROM         FKTable INNER JOIN
                      PKTable ON FKTable.fk = PKTable.pk
WHERE      PKTable.property = 5
UNION
SELECT     'True' AS UniqueCol, 'default' AS DiffCol
因此,基本上,'True','default')记录将始终存在于视图中,当有人试图在FKTable中插入一行并且它引用的PKTable记录的属性为5时,我会得到一个约束冲突,因为上面的union查询的第一部分将返回一些内容。无论如何,这就是我的想法。但是,SQLServer2005不允许对涉及联合的视图进行索引。然后我尝试创建另一个视图:

SELECT UniqueCol, DiffCol FROM TheViewAbove
在这种情况下,在UniqueCol上放置唯一索引失败,因为在引用另一个视图的视图上不能有索引。我知道这是不可能的。有什么办法可以解决这个问题吗

谢谢

两种方式

  • 创建一个子类型表(称为
    NonProp5s
    ,其中只有non属性=5行,然后从FKTable而不是主PKTable中引用此子类型表中的pk。此子类型表中不需要有pk列以外的任何内容,
    (创建表NonProp5s(pk Integer主键不为Null)
    关键在于,插入父pkTable时,总是会在
    非Prop5s
    中插入一行pk值相同的行,除非属性值等于5。(每当pkTable中的属性值更改为/从5更改时,您还需要一个更新触发器来插入/删除行。)
  • 创建2个触发器。其中一个触发器用于插入/更新FK表,如果您试图插入引用属性为的PK行的记录,该表将回滚事务 5,当PK表中有任何子记录时,若试图将属性更改为value=5,将回滚事务的PK表更新时的第二个触发器
  • 两种方式

  • 创建一个子类型表(称为
    NonProp5s
    ,其中只有non属性=5行,然后从FKTable而不是主PKTable中引用此子类型表中的pk。此子类型表中不需要有pk列以外的任何内容,
    (创建表NonProp5s(pk Integer主键不为Null)
    关键在于,插入父pkTable时,总是会在
    非Prop5s
    中插入一行pk值相同的行,除非属性值等于5。(每当pkTable中的属性值更改为/从5更改时,您还需要一个更新触发器来插入/删除行。)
  • 创建2个触发器。其中一个触发器用于插入/更新FK表,如果您试图插入引用属性为的PK行的记录,该表将回滚事务 5,当PK表中有任何子记录时,若试图将属性更改为value=5,将回滚事务的PK表更新时的第二个触发器
  • 在PKTable(pk,属性)上创建唯一约束
  • 将列PK_属性添加到子表中。使用检查约束确保(property5)
  • 有一个外键引用PKTable(pk,property)到PKTable(pk,property)
  • 在PKTable(pk,属性)上创建唯一约束
  • 将列PK_属性添加到子表中。使用检查约束确保(property5)
  • 有一个外键引用PKTable(pk,property)到PKTable(pk,property)

  • 我真的不想更改表或表之间的关系,因此我所做的是:

    我创建了一个名为
    DummyTable
    的表,其中包含多条记录。我在其中放入了2条记录。然后我构建了一个视图:

    SELECT pk FROM FKTable 
        INNER JOIN PKTable ON FKTable.fk = PKTable.pk
        INNER JOIN DummyTable ON 1 = 1
    WHERE PKTable.property = 5
    

    然后,我在视图的pk字段上放置了一个唯一索引。这样,当存在违反我约束的a行时,我将获得重复的索引。

    我真的不想更改表或表之间的关系,因此我所做的是:

    我创建了一个名为
    DummyTable
    的表,其中包含多条记录。我在其中放入了2条记录。然后我构建了一个视图:

    SELECT pk FROM FKTable 
        INNER JOIN PKTable ON FKTable.fk = PKTable.pk
        INNER JOIN DummyTable ON 1 = 1
    WHERE PKTable.property = 5
    

    然后,我在视图的pk字段上放置了一个唯一索引。这样,当存在违反我的约束的a行时,我将获得重复的索引。

    您还可以使用触发器来实现约束,如下所示:

    首先创建表:

    CREATE TABLE tPK(
    ID int NOT NULL PRIMARY KEY
    ,[Property] int NULL
    )
    go
    
    CREATE TABLE tFK(
    ID int NOT NULL PRIMARY KEY
    ,fk int NOT NULL
    )
    go
    
    ALTER TABLE tFK ADD
    CONSTRAINT FK1_tFK FOREIGN KEY(fk) REFERENCES tPK(ID)
        ON UPDATE CASCADE
        ON DELETE CASCADE
    go  
    
    然后将触发器添加到父表中

    CREATE TRIGGER trgPK ON tPK
        AFTER INSERT, UPDATE
    AS
    IF UPDATE(Property) 
        BEGIN
            DELETE  FROM tFK 
            WHERE   fk IN ( SELECT  T.ID
                            FROM    tPK AS T
                            WHERE   T.[Property] = 5 )
    
        END
    go
    
    在子表上:

    CREATE TRIGGER trgFK ON dbo.tFK
        AFTER INSERT, UPDATE
    AS
    IF UPDATE(fk) 
        BEGIN
            DELETE  FROM tFK 
            WHERE   fk IN ( SELECT  T.ID
                            FROM    tPK AS T
                            WHERE   T.[Property] = 5 )
    
        END
    GO
    
    如果要进行大量加载,则:

  • 禁用两个触发器
  • 加载数据
  • 启用两个触发器
  • 更新任一表中的行

  • 您还可以使用触发器来实现约束,如下所示:

    首先创建表:

    CREATE TABLE tPK(
    ID int NOT NULL PRIMARY KEY
    ,[Property] int NULL
    )
    go
    
    CREATE TABLE tFK(
    ID int NOT NULL PRIMARY KEY
    ,fk int NOT NULL
    )
    go
    
    ALTER TABLE tFK ADD
    CONSTRAINT FK1_tFK FOREIGN KEY(fk) REFERENCES tPK(ID)
        ON UPDATE CASCADE
        ON DELETE CASCADE
    go  
    
    然后将触发器添加到父表中

    CREATE TRIGGER trgPK ON tPK
        AFTER INSERT, UPDATE
    AS
    IF UPDATE(Property) 
        BEGIN
            DELETE  FROM tFK 
            WHERE   fk IN ( SELECT  T.ID
                            FROM    tPK AS T
                            WHERE   T.[Property] = 5 )
    
        END
    go
    
    在子表上:

    CREATE TRIGGER trgFK ON dbo.tFK
        AFTER INSERT, UPDATE
    AS
    IF UPDATE(fk) 
        BEGIN
            DELETE  FROM tFK 
            WHERE   fk IN ( SELECT  T.ID
                            FROM    tPK AS T
                            WHERE   T.[Property] = 5 )
    
        END
    GO
    
    如果要进行大量加载,则:

  • 禁用两个触发器
  • 加载数据
  • 启用两个触发器
  • 更新任一表中的行

  • @Nitai-那不行。你读对问题了吗?@Alex-我可能会按照你的建议去做。我以前做过,我不知道为什么我会回避改变这里的表格。@Nitai-那不行。你读对问题了吗?@Alex-我可能会按照你的建议去做。我以前做过,我不是我不知道为什么我不敢在这里换桌子。