SQL Server 2008:NOLOCK如何为CTE工作?

时间:2011-01-05 18:08:19

标签: sql-server sql-server-2008

我有所有使用NOLOCK的CTE。但是然后从父CTE中的那些CTE中选择使用儿童CTE并不使用NOLOCK,假设它已经是NOLOCK。最后的选择也不使用NOLOCK。

类似的东西:

with cte1 as
(select * from tab1 (nolock)),
cte2 as
(select * from cte1)

select * from cte2

或者我应该写

with cte1 as
(select * from tab1 (nolock)),
cte2 as
(select * from cte1 (nolock))

select * from cte2 (nolock)

感谢

4 个答案:

答案 0 :(得分:4)

您不需要外部nolock来避免在tab1上使用共享锁。您可以通过设置捕获locks类别中的各种事件的SQL事件探查器跟踪,过滤SSMS连接的spid并尝试两个版本来轻松验证这一点。

nolock是一个非常危险的设置,你是否知道使用它的所有可能的缺点(脏读,读数据两次或根本没有)?

答案 1 :(得分:1)

最里面的nolock就足够了,不需要为外部选择重复它。

您可以通过启动事务而不结束它来测试:

begin transaction
; with YourCte ( ...

然后,您可以使用Management Studio查看锁定。他们将在那里,直到交易超时。

答案 2 :(得分:1)

“外部”查询的NOLOCK也适用于任何内部查询。 CTE只是一个像视图或内联表udf的宏:仅此而已。所以你实际上有(忽略NOLOCK提示)

select * from (
               select * from (
                             select * from tab1
                             ) t1
               ) t2

来自Table Hints on MSDN,在“备注”下

  

所有锁定提示都会传播到查询计划访问的所有表和视图,包括视图中引用的表和视图。

在这种情况下,您只需要一个。无所谓。

重要的是你有JOIN的地方。如果cte1是2个表的连接,那么每个表都需要它。或者在更高/更高级别指定一次。

哦,我会和其他人一起加入:NOLOCK is a bad idea

答案 3 :(得分:0)

CTE的NOLOCK与其他所有内容的工作方式相同:它导致inconsistent results。请改用SNAPSHOT,参见SQL Server 2005 Row Versioning-Based Transaction Isolation