我正在创建一个与自我相关的表格:
表Item
列:
ItemId int - PK;
金额 - 不为空;
价格货币 - 使用UDF的计算列,根据项目祖先的金额检索值
ParentItemId int - 可以为null,引用此表中的另一个ItemId。
我需要避免循环,这意味着,兄弟姐妹不能成为他祖先的祖先,这意味着,如果ItemId = 2 ParentItemId = 1,则不应允许ItemId 1 ParentItemId = 2。
我不知道在这种情况下应该是什么样的最佳做法。 我想我应该添加一个从UDF或其他任何东西获得Scalar值的CK。
修改 另一个选择是创建一个INSTEAD OF触发器并在1个事务中放入ParentItemId字段的更新并从@@ RowIdentity中选择Price字段,如果它取消了事务失败,但我更喜欢UDF验证。
真诚欢迎任何想法。
答案 0 :(得分:1)
这肯定需要在数据库级别强制执行吗?
我只是问,因为我有这样的数据库(类似于此的表就像一个文件夹),我只确保在应用程序中设置了正确的父/子关系。
答案 1 :(得分:1)
这样的检查不容易实现,可能的解决方案可能会导致很多错误,问题可能比初始问题更难。通常,它足以为用户的输入添加控制并防止读取数据的无限循环。 如果你的应用程序使用存储过程,没有ORM,那么我会选择在SP中实现这个逻辑。否则 - 在其他层中处理它,而不是在DB
中处理它答案 2 :(得分:0)
现实生活中有多大问题?检测这些情况可能很昂贵(可能使用触发器)。实际上,在每次交易中,只有一小部分交易会导致这个问题,这可能会花费你很多精力。
首先考虑一下。
答案 3 :(得分:0)
一个简单的技巧是强制ParentItemId小于ItemId。这可以防止在这个简单的上下文中关闭循环。
但是,有一个缺点 - 如果您因某种原因需要删除/插入父级,您可能还需要按顺序删除/插入所有子级。
同样,需要按顺序插入层次结构,并且您可能无法重新分配父级。
答案 4 :(得分: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