在我的ERP应用程序中,我将一个名为'IsRemoved'的额外字段作为布尔值。每当用户删除任何记录时,记录不会被删除 - 只有其“IsRemoved”列的值为'true'。它可以帮助我们在需要时恢复数据,并且工作正常。
问题在于,当用户删除主表的记录时,我们如何检查其所有子表都没有引用此记录(因为我们不进行物理删除,我们只将“isremoved”字段标记为true)?
请向我提供任何查询或sp,我可以检查主记录是否用于任何孩子。
答案 0 :(得分:2)
根据经验,我必须告诉你这个设计很糟糕。考虑更改设计以将数据复制到“审计跟踪”表,然后将其从主表中物理删除。
如果您不考虑这一点,至少将其隐藏在VIEW
并尽一切可能避免将此暴露给想要查询数据库的任何人,使用INSTEAD OF
触发器必要时VIEW
。否则,期望应用程序出现频繁的错误,因为有人忘记添加使用此表的每个查询所需的AND isremoved = 0
谓词。
但这个'答案'并没有解决真正的问题。
是。抱歉,那个。但有时你必须治愈这种疾病,而不仅仅是治疗症状。
设计受到损害:表应该为单个实体类型建模,而这是建模两个。我该怎么说?因为OP已经声明,一旦'删除'实体有不同的数据要求,通过说“问题是......我们怎样才能检查所有子表没有引用此记录”。
所以'真正的'答案是:将实体移动到另一个不同的表。
但如果您从事治疗症状,那么这里就是答案:
IsRemoved
列添加到您的
所谓的'子'表,DEFAULT false
并确保
它是NOT NULL
。CHECK
约束
所谓的'孩子'表进行测试
isremoved = false
(或其他什么
'boolean'在你的SQL中意味着
产物)。UNIQUE
或PRIMARY KEY
)
所谓的“主人”表
(IsRemoved, <existing key columns
here>)
,或更改现有密钥
相应地。FOREIGN KEY
个约束
所谓'儿童'表可供参考
上面创建的复合键。答案 1 :(得分:1)
我认为对问题本身的评论是非常恰当的。在这一点上,这个问题很模糊。
但是,假设子表还有一个IsRemoved字段 - 毕竟如果主记录被标记为已删除,则子记录的剩余可用点是什么? - 为什么不在Master上实现一个触发器,如果更改IsRemoved,还会更改Child上的IsRemoved标志?
这样就完全消除了检查孩子主人身份状态的需要,因为他们将处于同步状态,因为它与活动或非活动状态有关。
答案 2 :(得分:0)
您是否可以在事务中插入替换记录,其中除IsRemove ='true'以外的所有值都相同,然后删除原始记录?这将为替换记录生成新的主键,以便不能保留旧的引用。
我假设您希望检测子引用已删除记录的情况,并将其视为错误。
答案 3 :(得分:0)
如果我们使用以下查询在所有子表中放置了适当的外键约束,您可以找到引用的主数据表表:
SELECT uc.table_name MAIN_TABLE_NAME,
ucc.column_name MAIN_TABLE_COLUMN_NAME,
ucc_ref.TABLE_NAME AS REFERENCED_TABLE_NAME,
ucc_ref.COLUMN_NAME AS REFERENCED_COLUMN_NAME,
ucc_ref.position
FROM USER_CONSTRAINTS uc,
USER_CONS_COLUMNS ucc_ref,
USER_CONS_COLUMNS ucc
WHERE uc.CONSTRAINT_TYPE = 'R'
AND uc.R_CONSTRAINT_NAME = ucc_ref.CONSTRAINT_NAME
AND ucc.Constraint_Name = uc.constraint_name
AND d ucc.table_name = uc.table_name
AND ucc_ref.position = ucc.position
AND uc.table_name = ?
ORDER BY ucc_ref.TABLE_NAME,ucc_ref.column_name
此查询在oracle中有效。我不确定其他数据库。
找到引用的表后,您需要查找您尝试删除的主数据记录是否存在于引用的表中。如果子表中存在活动记录,则可以抛出异常。这里的关键是仅仅找到引用的记录是不够的。我们可能会遇到在子表中找到主记录引用的情况,但子记录也已被取消。我们使用上述概念编写了一个用于删除主数据预检查的工具。
答案 4 :(得分:-2)
使用此逻辑:
SELECT t1.*
FROM Table1 AS t1
WHERE NOT EXISTS
( SELECT *
FROM Table2 AS t2
WHERE t2.FKcolumn = t1.PKcolumn
AND t2.columnX IS NULL
)