【问题标题】:Error from NOLOCK on CTE in SQL Server 2008 SP2SQL Server 2008 SP2 中 CTE 上的 NOLOCK 错误
【发布时间】:2011-08-16 07:31:59
【问题描述】:

我刚刚在我的工作站上设置了 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)

...抛出此错误:

消息 215,第 16 级,状态 1,第 6 行 为不是函数的对象“帖子”提供的参数。如果参数旨在作为表提示,则需要 WITH 关键字。

Posts 之后删除(NOLOCK) 让我的数据库很开心​​。

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

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

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

【问题讨论】:

  • 如果没有很好的理由,NOLOCK 应该只用于报告等实例...否则您可能会读取未提交的数据...

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


【解决方案1】:

从此页面: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)

不知道好不好,有没有效果。

【讨论】:

  • 在这种情况下,我们可以证明您对代码进行更改是合理的,谢谢。
【解决方案2】:

这似乎是特定于 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 中的结果都是一样的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多