1 Create Procedure testTran
 2 
 3 as
 4 
 5 declare @UserID int
 6 
 7 set nocount on
 8 
 9 begin tran AddUser
10 
11 insert into testTable(UserName,PassWord,Email) values ('milo','831105','milo42102126.com')
12 
13 if @@Error <> 0 or @@rowcount = 0 goto ErrMsg
14 
15 set @UserID = @@identity
16 
17 set nocount off
18 
19 commit tran AddUser
20 
21 return 1 --添加成功
22 
23 
24 ErrMsg:
25    set nocount off
26    rollback tran AddUser
27    return -1   --添加失败并回滚
28 
29 
30 GO
31

SET NOCOUNT ON 优化存储过程


客户端的应用程序中是没有用的,这些信息是存储过程中的每个语句的DONE_IN_PROC 信息。

我们可以利用SET NOCOUNT 来控制这些信息,以达到提高程序性能的目的。

MSDN中帮助如下:
  
SET NOCOUNT
使返回的结果中不包含有关受 Transact-SQL 语句影响的行数的信息。

语法
SET NOCOUNT { ON | OFF }

注释
当 SET NOCOUNT 为 ON 时,不返回计数(表示受 Transact-SQL 语句影响的行数)。当 SET NOCOUNT 为 OFF 时,返回计数。

即使当 SET NOCOUNT 为 ON 时,也更新 @@ROWCOUNT 函数。

当 SET NOCOUNT 为 ON 时,将不给客户端发送存储过程中的每个语句的 DONE_IN_PROC 信息。当使用   Microsoft SQL Server 提供的实用工具执行查询时,在 Transact-SQL 语句(如 select、_insert、 _update 和 _delete)结束时将不会在查询结果中显示"nn rows affected"。

如果存储过程中包含的一些语句并不返回许多实际的数据,则该设置由于大量减少了网络流量,因此可显著提高性能。

 

在查询分析器执行UPdate或Delete语句时,完成后会提示影响XX行记录,
当 SET NOCOUNT 为 ON 时执行完相关的操作不返回这个提示信息(根据实际情况有时候的确不需要此信息),通过该设置减少了网络流量而提高效率。
ON和OFF: 实际上就是一组开关,设置为on时,后面所有的相关sql都不再提示结果行数,设置为off时,就恢复原来状态了。 

1 
 2 use pubs   
 3 UPdate dbo.titles set title_ID = ltrim(title_ID  
 4 --执行完上面的sql显示  (所影响的行数为 18 行)
 5 UPdate dbo.titles set Title = ltrim(title)
 6 --(所影响的行数为 18 行)
 7 
 8 SET NOCOUNT on
 9 UPdate dbo.titles set title_ID = ltrim(title_ID)
10 --命令已成功完成。(没有行数提示了)
11 后面再执行什么sql都不会有行数提示了,除非 SET NOCOUNT off
12

SET NOCOUNT 设置是在执行或运行时设置,而不是在分析时设置。(是指在编程阶段,没办法设置这个属性,必须用语句执行设置)

权限
SET NOCOUNT 权限默认授予所有用户。

结论:我们应该在存储过程的头部加上SET NOCOUNT ON 这样的话,在退出存储过程的时候加上 SET NOCOUNT OFF(没有必要写,只是写作习惯罢了,有些设置在存储过程中开启后需要是关闭,免的影响其他的语句)这样的话,以达到优化存储过程的目的。

多说两句:

1:在查看SqlServer的帮助的时候,要注意“权限”这一节,因为某些语句是需要一定的权限的,而我们往往忽略。

2:@@ROWCOUNT是返回受上一语句影响的行数,包括找到记录的数目、删除的行数、更新的记录数等,不要认为只是返回查找的记录数目,而且@@ROWCOUNT要紧跟需要判断语句,否则@@ROWCOUNT将返回0。

3:如果使用表变量,在条件表达式中要使用别名来替代表名,否则系统会报错。

4:在CUD类的操作中一定要有事务处理。

5:使用错误处理程序,用来检查 @@ERROR 系统函数的 T-SQL 语句 (IF) 实际上在进程中清除了 @@ERROR 值,无法再捕获除零之外的任何值,必须使用 SET 或 select 立即捕获错误代码。