SQL 服务器内部加入使用 WITH(NOLOCK)

SQL Server Inner Join using WITH(NOLOCK)

我有一个数据库查询:

DECLARE @Pager_PageNumber AS INT, @Pager_PageSize AS INT; 

SET @Pager_PageNumber = 1; 
SET @Pager_PageSize = 12; 

SELECT 
    [Name], [Description], [Table1ID], [VersionNo], [Status] 
FROM
    (SELECT 
         CAST(Table1.name AS VARCHAR(MAX)) As [Name],
         CAST(Table1.description AS VARCHAR(MAX)) AS [Description],
         CAST(CAST(Table1.Table1_ID AS DECIMAL(18,0)) AS VARCHAR(MAX)) AS [Table1ID],
         CAST(CAST(Table1.VERSION_NO AS DECIMAL(18,0)) AS VARCHAR(MAX)) AS [VersionNo],
         CAST(Table2.br_status AS VARCHAR(MAX)) AS [Status]  
    FROM  
        Table1 WITH (NOLOCK)
    INNER JOIN 
        (SELECT 
             Table1_id, MAX(version_no) as version_no
         FROM Table1
         WHERE Table1.status = '00002'
         GROUP BY Table1_id) AS BR WITH (NOLOCK) ON Table1.Table1_id = BR.Table1_id 
                                                 AND BR.version_no = Table1.version_no 
    INNER JOIN 
        Table2 WITH (NOLOCK) ON Table1.status = Table2.br_status_code) A 
ORDER BY 
    [Name], [Description], [Table1ID], [VersionNo], [Status] 
    OFFSET ((@Pager_PageNumber - 1) * @Pager_PageSize) ROWS 
       FETCH NEXT @Pager_PageSize ROWS ONLY;

SELECT COUNT(*) 
FROM
    (SELECT 
         CAST(Table1.name AS VARCHAR(MAX)) AS [Name],
         CAST(Table1.description AS VARCHAR(MAX)) AS [Description],
         CAST(CAST(Table1.Table1_ID AS DECIMAL(18,0)) AS VARCHAR(MAX)) AS [Table1ID],
         CAST(CAST(Table1.VERSION_NO AS DECIMAL(18,0)) AS VARCHAR(MAX)) As [VersionNo],
         CAST(Table2.br_status AS VARCHAR(MAX)) AS [Status]  
    FROM  
        Table1 WITH (NOLOCK)  
    INNER JOIN
        (SELECT Table1_id, MAX(version_no) as version_no
         FROM Table1
         WHERE Table1.status = '00002'
         GROUP BY Table1_id) AS BR WITH (NOLOCK) ON Table1.Table1_id = BR.Table1_id 
                                                 AND BR.version_no = Table1.version_no 
    INNER JOIN 
        Table2 WITH (NOLOCK) ON Table1.status = Table2.br_status_code) A;

在 SQL 服务器中,我在 : BR WITH (NOLOCK) 附近收到错误:

Incorrect syntax near the keyword 'WITH'. Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.

但根据我从来源like的理解,语法是

SELECT 
    first_name, last_name,
FROM 
    dbo.person p WITH (NOLOCK)
JOIN 
    dbo.employee e WITH (NOLOCK) ON e.person_id = p.person_id
WHERE 
    p.person_id = 1;

所以,我的查询看起来是正确的。

此外,当我删除 BR WITH (NOLOCK) 旁边的 WITH (NOLOCK) 时,即我的内部连接查询,查询运行正常。关于我可能遗漏的任何想法?

PS: 我的数据库兼容级别是 110.

错误是 GROUP BY 子句中有 WITH (NOLOCK),而它应该只出现在 FROM 子句中:

 GROUP BY Table1_id) as  BR WITH (NOLOCK)

应该是

FROM Table1 WITH (NOLOCK)

这是从您发布的代码底部算起的 3 行。它也出现得更远。

你的代码更正(我想我已经全部搞定了!):

DECLARE @Pager_PageNumber AS INT, @Pager_PageSize AS INT; SET @Pager_PageNumber = 1; SET @Pager_PageSize = 12; SELECT [Name],[Description],[Table1ID],[VersionNo],[Status] FROM(SELECT CAST(Table1.name AS VARCHAR(MAX)) As [Name],CAST(Table1.description AS VARCHAR(MAX)) As [Description],CAST(CAST(Table1.Table1_ID AS DECIMAL(18,0)) AS VARCHAR(MAX)) As
 [Table1ID],CAST(CAST(Table1.VERSION_NO AS DECIMAL(18,0)) AS VARCHAR(MAX)) As [VersionNo],
 CAST(Table2.br_status AS VARCHAR(MAX)) As [Status]  FROM  Table1 WITH (NOLOCK)
  INNER JOIN (SELECT Table1_id, MAX(version_no) as version_no
    FROM Table1 WITH (NOLOCK)
    where Table1.status='00002'
    GROUP BY Table1_id) as BR ON Table1.Table1_id = BR.Table1_id AND BR.version_no=Table1.version_no 
    INNER JOIN Table2 WITH (NOLOCK) ON Table1.status = Table2.br_status_code )A 
    ORDER BY [Name],[Description],[Table1ID],[VersionNo],[Status] OFFSET ((@Pager_PageNumber - 1) * @Pager_PageSize)
     ROWS FETCH NEXT @Pager_PageSize ROWS ONLY;SELECT COUNT(*) FROM(SELECT CAST(Table1.name AS VARCHAR(MAX)) As 
     [Name],CAST(Table1.description AS VARCHAR(MAX)) As [Description],CAST(CAST(Table1.Table1_ID AS DECIMAL(18,0)) 
     AS VARCHAR(MAX)) As [Table1ID],CAST(CAST(Table1.VERSION_NO AS DECIMAL(18,0)) AS VARCHAR(MAX)) As [VersionNo],
     CAST(Table2.br_status AS VARCHAR(MAX)) As [Status]  FROM  Table1 WITH (NOLOCK)  INNER JOIN
      (SELECT Table1_id, MAX(version_no) as version_no
    FROM Table1 WITH (NOLOCK)
    where Table1.status='00002'
    GROUP BY Table1_id) as  BR
     ON Table1.Table1_id = BR.Table1_id AND BR.version_no=Table1.version_no INNER JOIN Table2 
     WITH (NOLOCK) ON Table1.status = Table2.br_status_code )A;

你能不能把WITH (NOLOCK)移到子查询里面?

本质上,这...

INNER JOIN ( SELECT Table1_id
                                       ,MAX(version_no) AS version_no
                                 FROM   Table1 WITH ( NOLOCK )
                                 WHERE  Table1.status = '00002'
                                 GROUP BY Table1_id
                               ) AS BR

完整代码

DECLARE @Pager_PageNumber AS INT
   ,@Pager_PageSize AS INT;
SET @Pager_PageNumber = 1;
SET @Pager_PageSize = 12;
SELECT  [Name]
       ,[Description]
       ,[Table1ID]
       ,[VersionNo]
       ,[Status]
FROM    ( SELECT    CAST(Table1.name AS VARCHAR(MAX)) AS [Name]
                   ,CAST(Table1.description AS VARCHAR(MAX)) AS [Description]
                   ,CAST(CAST(Table1.Table1_ID AS DECIMAL(18, 0)) AS VARCHAR(MAX)) AS [Table1ID]
                   ,CAST(CAST(Table1.VERSION_NO AS DECIMAL(18, 0)) AS VARCHAR(MAX)) AS [VersionNo]
                   ,CAST(Table2.br_status AS VARCHAR(MAX)) AS [Status]
          FROM      Table1 WITH ( NOLOCK )
                    INNER JOIN ( SELECT Table1_id
                                       ,MAX(version_no) AS version_no
                                 FROM   Table1 WITH ( NOLOCK )
                                 WHERE  Table1.status = '00002'
                                 GROUP BY Table1_id
                               ) AS BR ON Table1.Table1_id = BR.Table1_id
                                          AND BR.version_no = Table1.version_no
                    INNER JOIN Table2 WITH ( NOLOCK ) ON Table1.status = Table2.br_status_code
        ) A
ORDER BY [Name]
       ,[Description]
       ,[Table1ID]
       ,[VersionNo]
       ,[Status]
       OFFSET ( ( @Pager_PageNumber - 1 ) * @Pager_PageSize ) ROWS FETCH NEXT @Pager_PageSize
        ROWS ONLY;
SELECT  COUNT(*)
FROM    ( SELECT    CAST(Table1.name AS VARCHAR(MAX)) AS [Name]
                   ,CAST(Table1.description AS VARCHAR(MAX)) AS [Description]
                   ,CAST(CAST(Table1.Table1_ID AS DECIMAL(18, 0)) AS VARCHAR(MAX)) AS [Table1ID]
                   ,CAST(CAST(Table1.VERSION_NO AS DECIMAL(18, 0)) AS VARCHAR(MAX)) AS [VersionNo]
                   ,CAST(Table2.br_status AS VARCHAR(MAX)) AS [Status]
          FROM      Table1 WITH ( NOLOCK )
                    INNER JOIN ( SELECT Table1_id
                                       ,MAX(version_no) AS version_no
                                 FROM   Table1 WITH ( NOLOCK )
                                 WHERE  Table1.status = '00002'
                                 GROUP BY Table1_id
                               ) AS BR ON Table1.Table1_id = BR.Table1_id
                                          AND BR.version_no = Table1.version_no
                    INNER JOIN Table2 WITH ( NOLOCK ) ON Table1.status = Table2.br_status_code
        ) A;

您将 with (nolock) 应用于 ,而不是子查询。所以,而不是:

(SELECT Table1_id, MAX(version_no) as version_no
 FROM Table1
 where Table1.status='00002'
 GROUP BY Table1_id
) as BR WITH (NOLOCK)

你会写:

(SELECT Table1_id, MAX(version_no) as version_no
 FROM Table1 WITH (NOLOCK)
 where Table1.status='00002'
 GROUP BY Table1_id
) BR
DECLARE @Pager_PageNumber AS INT,
        @Pager_PageSize AS INT;

SELECT @Pager_PageNumber = 1, @Pager_PageSize = 12;

SELECT [Name],[Description],[BRMAINID],[VersionNo],[Status]
FROM (
    SELECT
        Table1.name As [Name],
        Table1.[description] As [Description],
        Table1.Table1_ID AS [BRMAINID],
        Table1.VERSION_NO AS [VersionNo],
        Table2.br_status AS [Status]
    FROM dbo.Table1 WITH(NOLOCK)
    JOIN (
        SELECT Table1_id, MAX(version_no) as version_no
        FROM dbo.Table1 WITH(NOLOCK)
        WHERE Table1.[status] = '00002'
        GROUP BY Table1_id
    ) AS BR ON Table1.Table1_id = BR.Table1_id AND BR.version_no=Table1.version_no 
    JOIN dbo.Table2 WITH(NOLOCK) ON Table1.status = Table2.br_status_code
) A 
ORDER BY [Name], [Description], [BRMAINID], [VersionNo], [Status]
    OFFSET ((@Pager_PageNumber - 1) * @Pager_PageSize)
    ROWS FETCH NEXT @Pager_PageSize ROWS ONLY

SELECT COUNT(*)
FROM dbo.Table1 WITH(NOLOCK)
JOIN (
    SELECT Table1_id, MAX(version_no) as version_no
    FROM dbo.Table1 WITH(NOLOCK)
    where Table1.[status] = '00002'
    GROUP BY Table1_id
) as BR ON Table1.Table1_id = BR.Table1_id AND BR.version_no=Table1.version_no
JOIN dbo.Table2 WITH(NOLOCK) ON Table1.status = Table2.br_status_code

试试...

就放

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

在您查询之前。 NOLOCK 行为将用于查询中的所有 table。使用提示 NOLOCK 仅意味着对特定 table.

使用 READ UNCOMMITTED 事务隔离级别