0

我正在创建一个自相关表:

Item列:
ItemId int - PK;
金额 - 不为空;Price money - 使用 UDF 的计算列,根据项目祖先的 Amount 检索值。
ParentItemId int - 可为空,引用此表中的另一个 ItemId。

我需要避免循环,这意味着兄弟姐妹不能成为他祖先的祖先,这意味着如果 ItemId=2 ParentItemId = 1,则不应允许 ItemId 1 ParentItemId = 2。

我不知道在这种情况下最好的做法是什么。我想我应该添加一个从 UDF 或其他任何东西获取标量值的 CK。

编辑: 另一个选项是创建一个 INSTEAD OF 触发器并将 ParentItemId 字段的更新放入 1 个事务中,并从 @@RowIdentity 中选择 Price 字段,如果它失败取消事务,但我更喜欢 UDF 验证。

任何想法都受到真诚的欢迎。

4

5 回答 5

1

这肯定需要在数据库级别强制执行吗?

我只是问,因为我有这样的数据库(与此类似的表就像一个文件夹),我只确保在应用程序中设置了正确的父/子关系。

于 2009-12-22T08:33:12.090 回答
1

像这样的检查并不容易实施,可能的解决方案可能会导致很多错误,并且问题可能比最初的问题更难。通常添加对用户输入的控制并防止读取数据的无限循环就足够了。如果你的应用程序使用存储过程,没有 ORM,那么我会选择在 SP 中实现这个逻辑。否则 - 在其他层中处理它,而不是在数据库中

于 2009-12-22T08:39:40.237 回答
0

这在现实生活中有多大的问题?检测这些情况可能会很昂贵(也许使用触发器)。事实上,在每笔交易中,当只有一小部分交易会导致此问题时,您可能会花费大量精力。

先考虑一下。

于 2009-12-22T08:31:26.023 回答
0

一个简单的技巧是强制 ParentItemId 小于 ItemId。这可以防止在这个简单的上下文中闭环。

但是,有一个缺点 - 如果您出于某种原因需要删除/插入父级,则可能还需要按顺序删除/插入其所有子级。

同样,需要按顺序插入层次结构,并且您可能无法重新分配父级。

于 2009-12-22T08:32:20.993 回答
0

经过测试并且效果很好:

CREATE TRIGGER Item_UPDATE
   ON Item
   FOR INSERT, UPDATE
AS 
BEGIN

BEGIN TRY
    SELECT Price FROM INSERTED
END TRY
BEGIN CATCH
    RAISERROR('This item cannot be specified with this parent.', 16, 1)
    ROLLBACK TRANSACTION;
END CATCH

END
GO
于 2009-12-22T09:42:12.757 回答