mssql中使用的一些常用又特殊的语句

1. SET NOCOUNT ON:
当 SET NOCOUNT 为 ON 时,不返回计数(表示受 Transact-SQL 语句影响的行数)。当 SET NOCOUNT 为 OFF 时,返回计数。如果存储过程中包含的一些语句并不返回许多实际的数据,则该设置由于大量减少了网络流量,因此可显著提高性能。

2. SET ANSI_NULLS ON:
SQL-92 标准要求在对空值进行等于 (=) 或不等于 (<>) 比较时取值为 FALSE。当 SET ANSI_NULLS 为 ON 时,即使 column_name 中包含空值,使用 WHERE column_name = NULL 的 SELECT 语句仍返回零行。即使 column_name 中包含非空值,使用 WHERE column_name <> NULL 的 SELECT 语句仍会返回零行。 

当 SET ANSI_NULLS 为 OFF 时,等于 (=) 和不等于 (<>) 比较运算符不遵从 SQL-92 标准。使用 WHERE column_name = NULL 的 SELECT 
语句返回 column_name 中包含空值的行。使用 WHERE column_name <> NULL 的 SELECT 语句返回列中包含非空值的行。此外,使用 
WHERE column_name <> XYZ_value 的 SELECT 语句返回所有不为 XYZ_value 也不为 NULL 的行。

3.SET QUOTED_IDENTIFIER ON:
当 SET QUOTED_IDENTIFIER 为 ON 时,标识符可以由双引号分隔,而文字必须由单引号分隔。当 
SET QUOTED_IDENTIFIER 为 OFF 时,标识符不可加引号,且必须符合所有 Transact-SQL 标识符规则。

4.WITH ( NOLOCK ):
大家在写查询时,为了性能,往往会在表后面加一个nolock,或者是with(nolock),其目的就是查询是不锁定表,从而达到提高查询速度的目的。

什么是并发访问:同一时间有多个用户访问同一资源,并发用户中如果有用户对资源做了修改,此时就会对其它用户产生某些不利的影响,例如:

1:脏读,一个用户对一个资源做了修改,此时另外一个用户正好读取了这条被修改的记录,然后,第一个用户放弃修改,数据回到修改之前,这两个不同的结果就是脏读。

2:不可重复读,一个用户的一个操作是一个事务,这个事务分两次读取同一条记录,如果第一次读取后,有另外用户修改了这个数据,然后第二次读取的数据正好是其它用户修改的数据,这样造成两次读取的记录不同,如果事务中锁定这条记录就可以避免。

3:幻读,指用户读取一批记录的情况,用户两次查询同一条件的一批记录,第一次查询后,有其它用户对这批数据做了修改,方法可能是修改,删除,新增,第二次查询时,会发现第一次查询的记录条目有的不在第二次查询结果中,或者是第二次查询的条目不在第一次查询的内容中。

为什么会在查询的表后面加nolock标识?为了避免并发访问产生的不利影响,SQL Server有两种并发访问的控制机制:锁、行版本控制,表后面加nolock是解决并发访问的方案之一。

1> 锁,每个事务对所依赖的资源会请求不同类型的锁,它可以阻止其他事务以某种可能会导致事务请求锁出错的方式修改资源。当事务不再依赖锁定的资源时,锁将被释放。

锁的类型:1:表类型:锁定整个表;2:行类型:锁定某个行;3:文件类型:锁定某个数据库文件;4:数据库类型:锁定整个数据库;5:页类型:锁定8K为单位的数据库页。

锁的分类还有一种分法,就是按用户和数据库对象来分:

1). 从数据库系统的角度来看:分为独占锁(即排它锁),共享锁和更新锁

1:共享 (S) :用于不更改或不更新数据的操作(只读操作),一般常见的例如select语句。

2:更新 (U) :用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。

3:排它 (X) :用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。

2). 从程序员的角度看:分为乐观锁和悲观锁。

1:乐观锁:完全依靠数据库来管理锁的工作。

2:悲观锁:程序员自己管理数据或对象上的锁处理。

一般程序员一看到什么锁之类,觉的特别复杂,对专业的DBA当然是入门级知识了。可喜的是程序员不用去设置,控制这些锁,SQLServer通过设置事务的隔离级别自动管理锁的设置和控制。锁管理器通过查询分析器分析待执行的sql语句,来判断语句将会访问哪些资源,进行什么操作,然后结合设定的隔离级别自动分配管理需要用到的锁。

2>:行版本控制:当启用了基于行版本控制的隔离级别时,数据库引擎 将维护修改的每一行的版本。应用程序可以指定事务使用行版本查看事务或查询开始时存在的数据,而不是使用锁保护所有读取。通过使用行版本控制,读取操作阻止其他事务的可能性将大大降低。也就是相当于针对所有的表在查询时都会加上nolock,同样会产生脏读的现象,但差别在于在一个统一管理的地方。说到了基于行版本控制的隔离级别,这里有必要说下隔离级别的概念。

隔离级别的用处:控制锁的应用,即什么场景应用什么样的锁机制。

最终目的:解决并发处理带来的种种问题。

隔离级别的分类:

1:未提交读,隔离事务的最低级别,只能保证不读取物理上损坏的数据;

2:已提交读,数据库引擎的默认级;

3:可重复读;

4:可序列化;隔离事务的最高级别,事务之间完全隔离。

小结:NOLOCK 语句执行时不发出共享锁,允许脏读 ,等于 READ UNCOMMITTED事务隔离级别 。nolock确实在查询时能提高速度,但它并不是没有缺点的,起码它会引起脏读。

nolock的使用场景(个人观点):

1:数据量特别大的表,牺牲数据安全性来提升性能是可以考虑的;

2:允许出现脏读现象的业务逻辑,反之一些数据完整性要求比较严格的场景就不合适了,像金融方面等。

3:数据不经常修改的表,这样会省于锁定表的时间来大大加快查询速度。

综上所述,如果在项目中的每个查询的表后面都加nolock,这种做法并不科学,起码特别费时间,不如行版本控制来的直接有效。而且会存在不可预期的技术问题。应该有选择性的挑选最适合的表来放弃共享锁的使用。

最后说下nolock和with(nolock)的几个小区别:

1:SQL05中的同义词,只支持with(nolock);

2:with(nolock)的写法非常容易再指定索引。

跨服务器查询语句时 不能用with (nolock) 只能用nolock
同一个服务器查询时 则with (nolock)和nolock都可以用
比如

SQL code

    select * from [IP].a.dbo.table1 with (nolock) 这样会提示用错误select * from a.dbo.table1 with (nolock) 这样就可以

5.@@ERROR:
如果前一个 Transact-SQL 语句执行没有错误,则返回 0。

如果前一个语句遇到错误,则返回错误号。如果错误是 sys.messages 目录视图中的错误之一,则 @@ERROR 将包含 sys.messages.message_id 列中表示该错误的值。可以在 sys.messages 中查看与 @@ERROR 错误号相关的文本信息。

由于 @@ERROR 在每一条语句执行后被清除并且重置,因此应在语句验证后立即查看它,或将其保存到一个局部变量中以备以后查看。

使用 TRY...CATCH 构造来处理错误。TRY...CATCH 构造也支持其他返回的错误信息多于 @@ERROR 的系统函数(ERROR_LINE、ERROR_MESSAGE、ERROR_PROCEDURE、ERROR_SEVERITY 和 ERROR_STATE)。TRY...CATCH 也支持 ERROR_NUMBER 函数,但不限制该函数在语句产生错误后立即在语句中返回错误号。

6.@@IDENTITY:
在一条 INSERT、SELECT INTO 或大容量复制语句完成后,@@IDENTITY 中包含语句生成的最后一个标识值。如果语句未影响任何包含标识列的表,则 @@IDENTITY 返回 NULL。如果插入了多个行,生成了多个标识值,则 @@IDENTITY 将返回最后生成的标识值。如果语句触发了一个或多个触发器,该触发器又执行了生成标识值的插入操作,那么,在语句执行后立即调用 @@IDENTITY 将返回触发器生成的最后一个标识值。如果对包含标识列的表执行插入操作后触发了触发器,并且触发器对另一个没有标识列的表执行了插入操作,则 @@IDENTITY 将返回第一次插入的标识值。出现 INSERT 或 SELECT INTO 语句失败或大容量复制失败,或者事务被回滚的情况时,@@IDENTITY 值不会恢复为以前的设置。

如果语句和事务失败,它们会更改表的当前标识,从而使标识列中的值出现不连贯现象。即使未提交试图向表中插入值的事务,也永远无法回滚标识值。例如,如果因 IGNORE_DUP_KEY 冲突而导致 INSERT 语句失败,表的当前标识值仍然会增加。

@@IDENTITY、SCOPE_IDENTITY 和 IDENT_CURRENT 是相似的函数,因为他们都返回插入到表的 IDENTITY 列的最后一个值。

@@IDENTITY 和 SCOPE_IDENTITY 可以返回当前会话中的所有表中生成的最后一个标识值。但是,SCOPE_IDENTITY 只在当前作用域内返回值,而 @@IDENTITY 不限于特定的作用域。

IDENT_CURRENT 不受作用域和会话的限制,而受限于指定的表。IDENT_CURRENT 可以返回任何会话和任何作用域中为特定表生成的标识值。有关详细信息,请参阅 IDENT_CURRENT (Transact-SQL)。

@@IDENTITY 函数的作用域是执行该函数的本地服务器上的当前会话。此函数不能应用于远程或链接服务器。若要获得其他服务器上的标识值,请在远程服务器或链接服务器上执行存储过程,并使(在远程或链接服务器的环境中执行的)该存储过程收集标识值,并将其返回本地服务器上的发出调用的连接。

复制可能会影响 @@IDENTITY 值,因为该值在复制触发器及存储过程中使用。如果此列是复制项目的一部分,则 @@IDENTITY 不是最近用户创建的标识的可靠指示器。您可以使用 SCOPE_IDENTITY() 函数语法代替 @@IDENTITY。

7.@@ROWCOUNT:

Transact-SQL 语句可以通过下列方式设置 @@ROWCOUNT 的值:

    将 @@ROWCOUNT 设置为受影响或被读取的行的数目。可以将行发送到客户端,也可以不发送。

    保留前一个语句执行中的 @@ROWCOUNT。

    将 @@ROWCOUNT 重置为 0 但不将该值返回到客户端。

执行简单分配的语句始终将 @@ROWCOUNT 值设置为 1。不将任何行发送到客户端。这些语句的示例如下:SET @local_variable、RETURN、READTEXT 以及不带查询 Select 语句,如 SELECT GETDATE() 或 SELECT 'Generic Text'。

在查询中执行分配或使用 RETURN 的语句将 @@ROWCOUNT 值设置为受查询影响或由查询读取的行数,例如:SELECT @local_variable = c1 FROM t1。

数据操作语言 (DML) 语句将 @@ROWCOUNT 值设置为受查询影响的行数,并将该值返回到客户端。DML 语句不会将任何行发送到客户端。

DECLARE CURSOR 和 FETCH 将 @@ROWCOUNT 值设置为 1。

EXECUTE 语句保留前一个 @@ROWCOUNT。

USE、SET <option>、DEALLOCATE CURSOR、CLOSE CURSOR、BEGIN TRANSACTION 或 COMMIT TRANSACTION 等语句将 ROWCOUNT 值重置为 0。查看更多我相关文章: http://52mvc.com/showtopic-668.aspx
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值