2012-07-18 21 views
1

我无法弄清楚这个问题的标题如何字要清楚,所以这里是在解释我最好的拍摄:如何最好地保持在父子关系状态

我的客户有一个一系列彼此处于亲子关系的表格。例如:

CREATE TABLE dbo.First_Level (
    id INT IDENTITY(1, 1) NOT NULL, 
    name VARCHAR(20) NOT NULL, 
    active BIT NOT NULL DEFAULT(1), 
    CONSTRAINT PK_First_Level PRIMARY KEY CLUSTERED (id) 
) 

CREATE TABLE dbo.Second_Level (
    id INT IDENTITY(1, 1) NOT NULL, 
    first_level_id INT NOT NULL, 
    name VARCHAR(20) NOT NULL, 
    active BIT NOT NULL DEFAULT(1), 
    CONSTRAINT PK_Second_Level PRIMARY KEY CLUSTERED (id), 
    CONSTRAINT FK_SecondLevel_FirstLevel FOREIGN KEY (first_level_id) REFERENCES dbo.First_Level (id) 
) 


CREATE TABLE dbo.Third_Level (
    id INT IDENTITY(1, 1) NOT NULL, 
    second_level_id INT NOT NULL, 
    name VARCHAR(20) NOT NULL, 
    active BIT NOT NULL DEFAULT(1), 
    CONSTRAINT PK_Third_Level PRIMARY KEY CLUSTERED (id), 
    CONSTRAINT FK_ThirdLevel_SecondLevel FOREIGN KEY (second_level_id) REFERENCES dbo.Second_Level (id) 
) 

棘手的部分是,如果父对象被标记为不再被激活(活性= 0),则其下任何的儿童,也应考虑为不再有效。但是,即使父母仍处于活动状态,子女可以将标记为不再有效。

我在寻找如何最好地执行这些业务规则的建议。我可以重叠视图,然后查看所有父母以确定任何给定行的最终活动标志,但我的客户端已经在这些表格中编写了大量代码。

我可以通过触发器执行规则,但我希望有一个更优雅的方式来做到这一点。

谢谢!

+0

触发器不是优雅的? – canon 2012-07-18 19:17:32

+1

@canon:不雅的人不是。 :) – 2012-07-18 19:44:15

+0

你需要知道什么标记为机构内存不活动?例如,如果某人将第三级别条目标记为非活动状态,则将其父级标记为非活动状态并将其更改为活动状态,您是否需要知道第三级别条目应该仍处于非活动状态? – HABO 2012-07-18 20:16:01

回答

0

您可以通过其在更新工作状态更新语句也更新了儿童执行业务规则:

-- Delete first level 
DECLARE @FirstLevelIdToDelete INT 
SET @FirstLevelIdToDelete = x 

UPDATE Third_Level 
SET  Third_level.active = 0 
FROM Third_Level tl 
JOIN Second_Level sl ON tl.second_level_id = sl.id 
WHERE sl.first_level_id = @FirstLevelIdToDelete 

UPDATE Second_Level 
SET  active = 0 
WHERE Second_Level.first_level_id = @FirstLevelIdToDelete 

UPDATE First_Level 
SET  active = 0 
WHERE id = @FirstLevelIdToDelete 

-- Delete second level 
DECLARE @SecondLevelIdToDelete INT 
SET @SecondLevelIdToDelete = x 

UPDATE Third_Level 
SET  active = 0 
WHERE Third_Level.second_level_id = @SecondLevelIdToDelete 

UPDATE Second_Level 
SET  active = 0 
WHERE id = @SecondLevelIdToDelete 

-- Delete third level 
DECLARE @ThirdLevelIdToDelete INT 
SET @ThirdLevelIdToDelete = x 

UPDATE Third_Level 
SET  active = 0 
WHERE id = @ThirdLevelIdToDelete 
+0

感谢您的建议。我相信前端使用存储过程来访问数据库,所以这可以在那里工作。尽管如此,ETL过程等并不需要同样的要求,所以它可能仍然会让一些不良数据通过。但是,由于缺乏更好的解决方案,这可能是我现在可以做的最好的。你目前在建议的解决方案的第一位;) – user1535855 2012-07-18 20:45:56

+0

因此触发..我认为你应该重新考虑这些。 – Randy 2012-07-18 22:07:25

+0

我不知道你是否可以遇到这种情况,但是如果用户想要“撤消”某个级别的“停用”,那么如何知道哪些孩子必须自动被“取消激活”连同他们的父母,还有哪些人必须保持原样,因为他们已经被禁用了?创造额外的价值来区分“用户禁用”和“触发器禁用”? – 2012-07-19 10:14:37

0

的一组当前活动的顶级项是对整个集的限制View顶级项目的顶层:

CREATE VIEW FIRST_LEVEL_ACTIVE AS SELECT * FROM FIRST_LEVEL使用活动...;

该组当前活动的第二级条目是那些满足该条件中,条目本身仍处于活动状态,和它们的父出现在刚刚定义的视图:

CREATE VIEW SECOND_LEVEL_ACTIVE AS(SELECT * FROM SECOND_LEVEL WHERE ACTIVE ...)NATURAL JOIN FIRST_LEVEL_ACTIVE;/*或任何其他与NATURAL JOIN具有相同效果的操作*/

当前活动的第三级条目集合是满足条件本身仍处于活动状态且其父条目出现在SECOND_LEVEL_ACTIVE中的条件集合

等等

对于处理UPDATE到这些视图,SQL标准有INSTEAD OF触发器。