SQL Server 2008 SP2中的CTE上NOLOCK出错

时间:2011-08-16 07:32:00

标签: sql-server sql-server-2005 sql-server-2008 sql-server-2008-r2

我刚在工作站上设置SQL Server 2008 SP2 以运行本地版本的数据库。生产数据库是SQL Server 2008 R2 。一位同事正在他的工作站上运行SQL Server 2005。

我的数据库使用以下代码抛出错误,而其他服务器上同一数据库的其他实例运行此查询时没有错误。

WITH Posts AS (
    SELECT TOP 10 *
    FROM TBL_MSG_LATEST (NOLOCK)
    WHERE TBL_MSG_LATEST.STATUS = 1
) 
SELECT * FROM Posts (NOLOCK)

...抛出此错误:

  

Msg 215,Level 16,State 1,Line 6   为对象'Posts'提供的参数不是函数。如果参数用作表提示,则需要WITH关键字。

(NOLOCK)之后移除Posts会让我的数据库感到满意。

我不熟悉SQL Server,所以我并不完全了解CTE,但我相信这里NOLOCK甚至可能不需要。

但是,我们不满意为了满足我的开发环境而对代码库进行更改。

我的新数据库环境是否存在配置差异?是否有正当理由删除我无法从错误消息中解密的NOLOCK

2 个答案:

答案 0 :(得分:4)

从此页面:http://msdn.microsoft.com/en-us/library/ms187373.aspx

  

省略WITH关键字是一项不推荐使用的功能,将被删除   在Microsoft SQL Server的未来版本中。

所以这会奏效。

WITH Posts AS (
    SELECT TOP 10 *
    FROM TBL_MSG_LATEST WITH (NOLOCK)
    WHERE TBL_MSG_LATEST.STATUS = 1
) 
SELECT * FROM Posts WITH (NOLOCK)

不知道这是不是一个好主意,或者是否有任何影响。

答案 1 :(得分:1)

这似乎是CTE语法特有的。添加“WITH”不会改变NOLOCK的工作方式;它只是允许它起作用。

在CTE中有NOLOCK提示,这些都有效:

WITH Posts AS (
    SELECT ... FROM TBL_MSG_LATEST NOLOCK
)
SELECT * FROM Posts NOLOCK;

WITH Posts AS (
    SELECT ... FROM TBL_MSG_LATEST WITH (NOLOCK)
)
SELECT * FROM Posts WITH (NOLOCK);

但这失败了:

WITH Posts AS (
    SELECT ... FROM TBL_MSG_LATEST (NOLOCK)
)
SELECT * FROM Posts (NOLOCK);

这些都在CTE之外工作:

SELECT ... FROM TBL_MSG_LATEST NOLOCK;
SELECT ... FROM TBL_MSG_LATEST (NOLOCK);
SELECT ... FROM TBL_MSG_LATEST WITH (NOLOCK);

正确的语法是“WITH(NOLOCK)”。

但是 ...如果你把NOLOCK放在CTE中,你为什么还把它放在SELECT上?

请注意,Denali CTP3中的结果完全相同。