我一直在使用以下模式来验证执行 INSERT 的存储过程的 FOREIGN KEY (FK) 参数:
CREATE PROC spCreateChildFoo
@ForeignKey_Id int,
@Attribute varchar(50)
AS
IF NOT EXISTS (SELECT ForeignKey_Id FROM ForeignTable WHERE ForeignKey_Id = @ForeignKey_Id)
BEGIN
RAISERROR ('The input ForeignKey_Id does not exist', 16, 1)
RETURN;
END
INSERT INTO ChildTable (ForeignKey_Id, Attribute)
VALUES (@ForeignKey_Id, @Attribute)
我这样做是因为我想在插入任何数据之前在执行存储过程的早期捕获错误的 FK 条目,尤其是对于执行多个 INSERT 的过程。我还认为这是返回准确错误消息以简化调试的好方法。这种模式可以很好地服务于这两个目标。
问题
这是在浪费时间吗?
更具体地说,我是否应该仅依靠 FK 约束来验证 FK 参数并在失败时回滚?
随着数据库的增长,它最终会损害我的应用程序的性能吗?
是的,至少当您的存储过程只是可能导致外键冲突的 INSERT 语句时,这是浪费时间。如果存在外键,则数据库引擎本身会根据引用表验证任何尝试的 FK 值。
如果引用表中不存在该值,您将收到异常并中止 INSERT 语句。
所以,这就足够了:
另一方面,如果您的过程不止一个 INSERT 语句,并且您希望在其开始时在无效插入时中止整个过程,那么初步检查 FK 值可能并非完全没有意义。但是,有效的 FK 值仍然会导致重复查找,这既不好也没有必要。要达到中止整个过程的相同效果,您可以将过程的主体放入 TRY/CATCH 块中:
更多信息: