2009-11-27 198 views
0
我有问题拿出足够的克制在SQL Server 2005中我的问题涉及如下表

SQL Server的约束帮助

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 

所以基本上,(“真”,“默认”)记录将始终存在于视图,当有人试图将行插入FKTable和它引用的PKTable记录具有属性= 5,我因为上面的联合查询的第一部分会返回一些东西,所以得到一个约束违规。无论如何,这是主意。但是,SQL Server 2005不允许在涉及联合的视图上使用索引。然后我试图创建另一种观点认为:在这种情况下

SELECT UniqueCol, DiffCol FROM TheViewAbove 

上UniqueCol把唯一索引失败,因为你不能对引用另一个视图的视图索引。我知道这是一个长镜头。任何方式来解决这个问题?

谢谢!

回答

0

我真的不想更改表或所以在这里表之间的关系是我做过什么:

我创建了一个表中调用DummyTable在它超过1分的纪录。我把2放在里面。然后我建立了一个视图:

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

然后,我在视图中的pk字段上添加了一个唯一索引。这样,当行存在违反我的约束时,我会得到重复。

2

两种方式。

  1. 创建一个亚型表(说这就是所谓的NonProp5s,在它只有非财产= 5行,然后引用从FKTable而不是主PKTable这种亚型表的PK,这并不需要有什么比它的PK列多,(Create Table NonProp5s (pk Integer Primary Key Not Null)关键是插入到母pkTable总是行插入NonProp5s,具有相同的PK值,除了其中属性值等于5(你会还需要一个更新触发插入/删除行每当PKTable变化到/从5)
  2. 属性值创建2个触发器。一个上插入/更新到FK表THA如果您试图插入一个引用PK行的记录,并且属性= 5,并且第二次触发PK表的更新时,如果尝试将属性更改为值= 5时回滚事务(如果存在任何子节点),则回滚事务记录在FKTable中。
1
  1. 创建于PKTable唯一约束(PK,财产)
  2. 添加列PK_property到您的子表。有一个检查约束保证(财产<> 5)
  3. 有一个外键参考(PK,pk_property)到PKTable(PK,财产)
+0

@Nitai - 这是行不通的。你是否正确地阅读了这个问题? @Alex - 我可能最终会做你的建议。我之前做过,我不确定为什么我不想改变这里的桌子。 – Jordan 2009-11-27 18:23:02

0

你也可以使用一个触发器来实现的限制,像这样:

首先创建表:

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 

如果你有大量装载做,那么:

  1. 禁用两个触发器,
  2. 负载数据,
  3. 同时启用触发器,
  4. 更新在任一表中的一行。