【问题标题】:SQL Server Inner Join using WITH(NOLOCK)SQL Server 内连接使用 WITH(NOLOCK)
【发布时间】:2016-03-08 01:08:45
【问题描述】:

我有一个数据库查询:

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 Server 中,我在附近遇到错误:BR WITH (NOLOCK) 那:

关键字“WITH”附近的语法不正确。 关键字“with”附近的语法不正确。如果这个语句是一个公用表表达式、一个 xmlnamespaces 子句或一个更改跟踪上下文子句,则前面的语句必须以分号结束。

但根据我对来源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:我的 DB 兼容级别是 110。

【问题讨论】:

  • 请在发布前格式化您的查询 - sql-format.com
  • 设置Bad Habits to kick - putting NOLOCK everywhere - 不推荐在任何地方使用它 - 恰恰相反!
  • 我建议尽可能删除 WITH (NOLOCK)。此语句允许您包含脏读,这意味着它可能会为您的事务生成错误,向用户提供从未提交的数据,或导致用户看到两次记录(或根本看不到)。更多信息请见:msdn.microsoft.com/en-GB/library/ms187373.aspx.
  • @SyedOsamaMaruf,首先给了你答案,甚至格式化了你的代码,我得到的只是一个赞成票哈哈:) 我肯定会领导什么marc_s 是建议。

标签: sql sql-server join inner-join self-join


【解决方案1】:

您将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

【讨论】:

    【解决方案2】:

    随便放

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    

    在您查询之前。 NOLOCK 行为将用于查询中的所有表。使用提示 NOLOCK 只是意味着对特定表使用 READ UNCOMMITTED 事务隔离级别。

    【讨论】:

    • 同志,很高兴在这里见到你;)
    • 哦,太好了,现在我有足够的声誉来评论帖子了 :) 你好 :)
    【解决方案3】:

    错误是您在 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;
    

    【讨论】:

      【解决方案4】:

      不能移动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;
      

      【讨论】:

        【解决方案5】:
        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
        

        试试吧……

        【讨论】:

          猜你喜欢
          • 2020-04-28
          • 1970-01-01
          • 1970-01-01
          • 2020-10-01
          • 1970-01-01
          • 2014-02-02
          • 2011-01-14
          • 2013-10-14
          • 1970-01-01
          相关资源
          最近更新 更多