1

在以下查询中,我将放置在哪里WITH(NOLOCK)

SELECT *
FROM   (SELECT *
        FROM   (SELECT *
                FROM   (SELECT *
                        FROM   (SELECT *
                                FROM   dbo.VBsplit(@mnemonicList, ',')) a) b
                       JOIN dct
                         ON dct.concept = b.concept
                WHERE  b.geo = dct.geo) c
               JOIN dct_rel z
                 ON c.db_int = z.db_int) d
       JOIN rel_d y
         ON y.rel_id = d.rel_id
WHERE  y.update_status = 0
GROUP  BY y.rel_id,
          d.concept,
          d.geo_rfa 
4

3 回答 3

10

您不应该NOLOCK在该查询中放置任何位置。如果您试图阻止读者阻止作者,一个更好的选择是READ COMMITTED SNAPSHOT. 当然,您应该阅读有关此内容的内容,就像NOLOCK在盲目地将其放入查询中之前应该阅读的内容一样:

此外,由于您使用的是 SQL Server 2008,因此您可能应该VBSplit()用表值参数替换您的函数 - 这将比拆分字符串更有效,即使该函数是隐含在 CLR 中的。

首先,创建一个可以容纳适当字符串的表类型。我将假设该列表保证是唯一的,并且单个助记词不能超过 900 个字符。

CREATE TYPE dbo.Strings AS TABLE(Word NVARCHAR(900) PRIMARY KEY);

现在,您可以创建一个采用此类型参数的过程,并在一个位置设置您选择的隔离级别:

CREATE PROCEDURE dbo.Whatever
  @Strings dbo.Strings READONLY
AS 
BEGIN
  SET NOCOUNT ON;
  SET TRANSACTION ISOLATION LEVEL --<choose wisely>;

  SELECT -- please list your columns here instead of *
    FROM @Strings AS s
    INNER JOIN dbo.dct -- please always use proper schema prefix
    ON dct.concept = s.Word
    ...
END
GO

现在,您可以简单地从您的应用程序中传递一个集合(例如 DataTable),无论是 C# 还是其他,而根本不必组装或解构一个杂乱的逗号分隔列表。

于 2013-08-16T13:50:11.450 回答
3

既然问题真的是,“我应该把 NOLOCK 放在哪里”。我不会讨论使用 OR 重新格式化查询以更好的连接。我只会回答这个问题。

我绝不打算说这是更好的方法,或者说其他答案不好。另一个答案解决了实际问题。我只是想在问题询问时显示锁定提示的确切位置

SELECT *
FROM   (SELECT *
        FROM   (SELECT *
                FROM   (SELECT *
                        FROM   (SELECT *
                                FROM   dbo.VBsplit(@mnemonicList, ',')) a) b
                       JOIN dct WITH (NOLOCK) --        <---
                         ON dct.concept = b.concept
                WHERE  b.geo = dct.geo) c
               JOIN dct_rel z WITH (NOLOCK) --        <---
                 ON c.db_int = z.db_int) d
       JOIN rel_d y WITH (NOLOCK) --        <---
         ON y.rel_id = d.rel_id
WHERE  y.update_status = 0
GROUP  BY y.rel_id,
          d.concept,
          d.geo_rfa 
于 2013-08-16T14:48:18.553 回答
2

像这样,要使用最整洁的方法。

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM (SELECT * FROM 
(SELECT * FROM (SELECT * FROM 
(SELECT * FROM dbo.VBsplit(@mnemonicList,',')) a ) b 
JOIN dct ON dct.concept = b.concept WHERE b.geo = dct_variable.geo_rfa) c
JOIN dct_rel z ON c.db_int = z.db_int) d
JOIN rel_d y ON y.rel_id = d.rel_id
WHERE y.update_status = 0
GROUP BY y.rel_id,d.concept,d.geo_rfa
SET TRANSACTION ISOLATION LEVEL READ COMMITTED

但是,除非您将其用于报告活动数据库的目的,否则启用脏读可能不是最好的方法。

编辑为 (NOLOCK) 本身不被弃用,除非此处描述:http ://technet.microsoft.com/en-us/library/ms143729.aspx 。

于 2013-08-16T13:48:15.087 回答