首页 > 解决方案 > 使用存储过程中的更新语句发出测试错误处理

问题描述

我无法理解为什么代码不起作用。表中有数据vendorproducts,但是执行后没有检索到数据,并且在我传入时也没有打印错误@vendor=1

ALTER PROCEDURE HW5UD1
    @vendor VARCHAR(64),
    @Perct DECIMAL(3,2)
AS
BEGIN TRANSACTION
BEGIN TRY
    UPDATE VendorProducts 
    SET paidPrice = paidPrice * (1 + @perct)
    WHERE vendor = @vendor
END TRY
BEGIN CATCH
   ROLLBACK TRANSACTION
   PRINT 'Error occurred while trying to update vendor products table'
   RETURN -11001
END CATCH

COMMIT TRANSACTION

SELECT * 
FROM VendorProducts
WHERE vendor = @vendor

RETURN 0

标签: sql-server

解决方案


评论太长了,让我们开始吧。首先,学会提出聪明的问题。您需要多长时间才能显示任何错误消息?您发布了完整的消息还是缩写版本?

ALTER PROCEDURE HW5UD1

重来。这个名字没用。任何阅读您的代码(或调用此过程的代码)的人都应该通过阅读该名称来了解您的过程的作用。

让我们看看你如何调用这个过程。您首先说您使用“@vendor=1”调用此过程。稍后您说“供应商意味着像 DVDemporium 这样的供应商名称”。这里似乎有些错误和不一致。从模式的角度来看,您应该有一个从 VendorProducts 到 Vendors 的外键 (FK)。你?你甚至有供应商表吗?FK 列是 varchar 还是 numeric?我希望是数字,因为您传递了一个值 1。

接下来,您的过程包含一个 DML 语句。单个语句(更新 - 在这种情况下)是原子的,并且将成功或不成功。没有必要进行交易。如果在调用此过程之前启动了事务,则您现在已经嵌套了一个事务,没有任何特殊原因。更糟糕的是,您捕获任何错误,然后在抛出您自己的错误时隐藏 TRUE 错误。您只是通过隐藏使调试任何实际错误变得不可能。tsql 中的错误处理很复杂 - 我建议您阅读Erland 的讨论

在您的 CATCH 子句中,您使用 print。不——不要。不要尝试使用 print 从过程(或触发器)提供“输出”。这些以大多数调用者不期望也不会处理的方式返回给调用者(完全或按照开发人员的意图)。他们只是产生额外的工作。它可用于调试目的,但不应出现在生产代码中。因为你抛出一个错误,调用者隐含地知道“发生错误......” - 你的打印消息没有添加任何有用的东西。

该过程中的最后一条语句只是从您尝试更新的表中选择行。为什么?如果呼叫者在呼叫时拥有所有这些信息,那么这只会产生额外的“工作”。如果调用者没有,那么您为什么假设调用者想要或需要此信息。一般来说,你的程序应该做一件“事情”。只需更新行。

所以也许这一切都是学习的练习。不幸的是,人们倾向于提供工作代码而没有太多解释。当然,您可以直接复制并上交成绩。但是你不会学到很多东西(如果有的话),这是不幸的。如果没有理解和学习,您将无法发展成为有效开发人员所需的技能。

最后,还有很多关于 tsql 编码最佳实践的讨论。这些你应该阅读并开始实施。


推荐阅读