更新:从评论中发现我的问题应该更具体。每个人都有一些他们在代码中使用的SP的技巧,我期望得到这些技巧和实践,这些技巧和实践使他们与其他人不同,并且更重要的是增强了编写和使用存储过程的生产力。
When executing a stored procedure, always check both @@error and the return value. For example:
EXEC @err = AnyStoredProc @value
SET @save_error = @@error
-- NULLIF says that if @err is 0, this is the same as null
-- COALESCE returns the first non-null value in its arguments
SELECT @err = COALESCE( NULLIF(@err, 0), @save_error )
IF @err <> 0 BEGIN
-- Because stored proc may have started a tran it didn't commit
ROLLBACK TRANSACTION
RETURN @err
END
Always store and check @@error after the following statements:
INSERT, DELETE, UPDATE
SELECT INTO
Invocation of stored procedures
invocation of dynamic SQL
COMMIT TRANSACTION
DECLARE and OPEN CURSOR
FETCH from cursor
WRITETEXT and UPDATETEXT
我经常使用的一个技巧是:在接近顶部的注释中始终包含一个使用示例。这对于测试你的存储过程也很有用。我喜欢包含最常见的示例 - 这样你甚至不需要 SQL Prompt 或一个单独的 .sql 文件来调用它,因为它存储在服务器中(如果你有存储过程查看 sp_who 输出以查找阻塞或其他内容,并且需要大量参数,则特别有用)。
比如:
/*
Usage:
EXEC usp_ThisProc @Param1 = 1, @Param2 = 2
*/
然后,要测试或运行SP,只需在脚本中突出显示该部分并执行即可。
SET NOCOUNT ON
BEGIN TRAN
INSERT...
UPDATE...
COMMIT
更好一些,但看起来很混乱,而且编写代码会非常麻烦:SET NOCOUNT ON
BEGIN TRAN
INSERT...
IF @ErrorVar <> 0
BEGIN
RAISERROR(N'Message', 16, 1)
GOTO QuitWithRollback
END
UPDATE...
IF @ErrorVar <> 0
BEGIN
RAISERROR(N'Message', 16, 1)
GOTO QuitWithRollback
END
EXECUTE @ReturnCode = some_proc @some_param = 123
IF (@@ERROR <> 0 OR @ReturnCode <> 0)
GOTO QuitWithRollback
COMMIT
GOTO EndSave
QuitWithRollback:
IF (@@TRANCOUNT > 0)
ROLLBACK TRANSACTION
EndSave:
好:
SET NOCOUNT ON
SET XACT_ABORT ON
BEGIN TRY
BEGIN TRAN
INSERT...
UPDATE...
COMMIT
END TRY
BEGIN CATCH
IF (XACT_STATE()) <> 0
ROLLBACK
END CATCH
最佳方案:
SET NOCOUNT ON
SET XACT_ABORT ON
BEGIN TRAN
INSERT...
UPDATE...
COMMIT
那么,“最佳”解决方案的错误处理在哪里?你不需要任何东西。看到SET XACT_ABORT ON,这意味着如果有任何错误,则执行自动回滚。代码更加简洁易读、易写、更加健壮。更加健壮是因为现在 SQL Server 会为你处理错误条件,不存在遗漏错误条件的可能性。
这是一个非常普遍的问题,但是以下是几个建议:
当然还有更多内容。以下链接提供了更多信息: SQL Server 存储过程优化技巧
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'usp') AND type in (N'P', N'PC')) DROP PROCEDURE usp
这不是一个可以直接回答的问题,需要更多的信息,但是有一些通用的经验法则确实适用。
存储过程只是存储的T-SQL查询。因此,你需要更加熟悉T-SQL和各种函数和语法。从性能的角度来看,你需要确保查询和底层数据结构匹配,以便获得良好的性能。例如,确保在需要时实现索引、关系、约束等。
了解如何使用性能调整工具,了解执行计划的工作原理等方面,是你达到“下一个级别”的方法。
BEGIN TRY
one_or_more_sql_statements
END TRY
BEGIN CATCH
one_or_more_sql_statements
END CATCH
ERROR_NUMBER()
ERROR_MESSAGE()
ERROR_SEVERITY()
ERROR_STATE()
ERROR_LINE()
ERROR_PROCEDURE()
与每个执行的语句重置的@@error不同,由错误函数检索到的错误信息在TRY...CATCH语句的CATCH块范围内始终保持不变。这些函数可以将错误处理模块化为单个过程,因此您无需在每个CATCH块中重复错误处理代码。
基础内容:
制定错误处理策略,并在所有 SQL 语句中捕获错误。
决定存储过程源代码控制的使用策略。
包括带有用户、日期/时间和 sp 目的的注释头。
明确返回 0(成功)以表示成功执行,否则返回其他内容。
对于非平凡的存储过程,包括一个或多个测试用例和预期结果的描述。
养成性能测试的习惯。对于文本案例,至少记录执行时间。
了解显式事务并使用它们。
几乎不要从存储过程中调用 SP。在 SQL 中,可重用性是一种不同的游戏。
以下是一些最佳实践: