我有所有使用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)
感谢
答案 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。