2010-12-01 39 views
0

私はBOLフレーズで混乱しています:UPDATEまたはDELETEステートメントのターゲットテーブルに適用されるFROM句でNOLOCKが無視されるのはなぜですか?

「READUNCOMMITTEDおよびNOLOCKを挿入、更新、または削除操作によって変更された表には指定できませんSQL Serverクエリオプティマイザは、FROM句にREADUNCOMMITTEDおよびNOLOCKヒントを無視します。それは例えば、「[1]

をUPDATEのターゲット表に適用するか、またはDELETEステートメント私は

--script 1) 
UPDATE Test SET Txt=(Select Txt from TEST WITH(NOLOCK) where ID=1) 
WHERE ID=1 

を書いた場合、それはエラー(または警告なしで実行されますまた、エラーや警告なしで実行される

--script 2) 
set transaction isolation level SERIALIZABLE; 
begin tran 
Declare @nvarm nvarchar(max); 

Select @nvarm=Txt from Test where ID=1; 
--Select @nvarm; 
UPDATE Test SET [email protected] WHERE ID=1; 
commit; 

とおそらく同等です。
これは同等ですか?

テーブルが同じであるが、それから、私は1再書かれている可能性が論理的ターゲットテーブル ソーステーブルはない)別の(物理)表などの異なるソーステーブルを有する:

--script 3) 
select * 
into testDup 
from TEST; 

GO; 

UPDATE Test SET Txt=(SELECT Txt FROM TestDUP WITH(NOLOCK) where ID=1) 
    WHERE ID=1 

他のテーブルでNOLOCKを無視するのはなぜですか?
または、それが間違っている場合質問
物理テーブルが1)と2)であっても、「UPDATEまたはDELETEステートメントのターゲットテーブルに適用されるFROM句にNOLOCKヒントを持つ」UPDATEを書き込む方法同じですが論理的には、ソース(SELECT内)表とターゲット(UPDATE内)表は異なるものです。

WITH(NOLOCK)が無視されていることを示すUPDATE文を書く方法は?
何も無視する必要がありますか?それは無視されますか?
質問が間違っている場合は、
なぜ構文で無視されることが保証されているのですか?

もう一度、文書に書かれているような文章を書くことは不可能ですか(あるいはそれを無視しているのでしょうか? )...

UPDATE2:
答えは、BOL docs [1]によってアサートされているUPDATE文のFROM句でNOLOCKが無視(更新)されないことを示しています。
まあ、この質問の本質:
私は、UPDATE文のFROM句でNOLOCKの無視が意味をなさない例(文脈)を教えていただけますか?

UPDATEまたはDELETE文のFROM句[1]
テーブルヒント(Transact-SQL)
のSQL Server 2008 R2
http://msdn.microsoft.com/en-us/library/ms187373.aspx

答えて

2

ザ・はあなたの例のいずれにおいても明らかではありません。サブクエリにはfrom句がありますが、それらは同じものではありません。ここで

はUPDATEのためにFROM句です:

UPDATE t 
SET Col = u.Val 
FROM /* <-- Start of FROM clause */ 
    Table t WITH (NOLOCK) 
     inner join 
    Table2 u 
     on 
      t.ID = u.ID 
/* End of FROM clause */ 
WHERE 
    u.Colx = 19 

そして、ドキュメントが声をかけて、WITH (NOLOCK)は、この場合には無視されます。なぜこれが無視されるのが許されるのかについては、同じクエリのSELECTバージョンでそのようなヒントが有効であり、人々は頻繁にSELECTを書くことになります。行/列)を入力して、SELECT句をUPDATE/SET句のペアに置き換えます。残りのクエリは変更されません。


vgv8からのコメント/ "答え" をもとに更新:あなたの例の更新はまだでUPDATE文のFROM句

を見ていない

以下であっても、正常に動作します

UPDATE T SET Txt= td.Txt 
FROM TEST t inner join TESTDUP td WITH (NOLOCK) on t.ID = td.ID 
where t.ID = 1 
+0

「Table2 u WITH(NOLOCK)」のNOLOCKは無視されますか? –

+0

@ vgv8 - 私は、NOLOCKヒントは、更新対象のテーブル以外のテーブル(したがって、ドキュメント内のターゲットテーブルへの参照)で尊重されると考えています。 –

+0

エイア、これは常識的な希望ですが、事実は異なります。私の答えを見るhttp://stackoverflow.com/questions/4322368/why-nolock-is-ignored-in-the-from-clause-that-apply-to-the-target-table-of-an-up/4324639 #4324639 –

0

2つの同一のテーブルを作成して塗りつぶしたTestとTestDUP [ 1]、1回のセッションで(SSMSのウィンドウ)Iは、実行ブロックは、例えば、同じテーブル上の別のセッション(SSMSのウィンドウ)の中から選択

--2) 
begin tran 
Select Txt from TestDUP with(TABLOCKX) 
WHERE ID=1 
--rollback 

--3.1) 
select * from TestDUP 

なく

--3.2) 
select * from TestDUP WITH(NOLOCK) 

3.1)はブロックされていますが、3.2)はブロックされていません。

ものの理由は、WITH(NOLOCK)ブロックされているTestDUP

--4)WITH(NOLOCK) is not honored until completing 
-- (commit/roollback)-ing transaction 2) 
UPDATE Test SET Txt= 
(Select Txt from TESTDUP WITH(NOLOCK) where ID=1) 
    WHERE ID=1; 

からSELECT使用して別のテーブルTESTに更新し、他のソーステーブルの上に、UPDATE文のFROM句では無視されます。

更新:

--4.1)WITH(NOLOCK) is honored 
-- in FROM clause of UPDATE statement 
UPDATE Test SET Txt= td.Txt 
FROM TESTDUP td WITH (NOLOCK) 
where test.ID = 1 

--4.2) Note that without NOLOCK this script is blocked 
-- until first transaction 2) completes (rollbacks or commits) 
UPDATE Test SET Txt= td.Txt 
FROM TESTDUP td WITH (NOLOCK) 
where test.ID = 1 

だから、それはないそれが今で理にかなっていますが、UPDATE文のFROM句にNOLOCKので、マニュアルを矛盾は無視されていない、いますか?

[1]
2つの同じ充填テーブルテストおよびtestDUPを作成しない:

if object_id('Test') IS not NULL 
drop table Test; 

CREATE TABLE Test (
    ID int IDENTITY PRIMARY KEY, 
    Txt nvarchar(max) NOT NULL 
) 
GO 
----------- 
INSERT INTO Test 
SELECT REPLICATE(CONVERT(nvarchar(max), 
    CHAR(65+ABS(CHECKSUM(NEWID()))%26)),100000) 
GO 10 

--COPYING TEST into TESTDUP with creating of the latter 
select * 
into testDup 
from TEST; 
3

不要推測します。

SybaseおよびMS SQLサーバは、自動的な2PLリソースの自動ロックを使用しますが、ISO/IEC/ANSI SQL標準に完全に準拠しています。考えられるすべての組み合わせを理解しようとすると、構文が愚かになります。いくつかの節はすべてのコマンドに関連しないからです。マニュアルを言おうとしているが、簡単な英語で言っていない何

、次のとおりです。

    どんなアウター操作のための
  • 、またはトランザクション内の単一のクエリ、あなたは、することができます実行しているSET ISOLATION LEVEL
  • UNCOMMITTED, NOLOCK, HOLDLOCK構文を使用して指定することもできます
  • 外部クエリに1つのILがあるか、トランザクション内で1つのクエリが使用されますが、内部クエリに別のILを使用することができます変調器の内部クエリ)
  • はあなたがIL3で実行されるトランザクションを持っている、とIL0で実行し、その中の1 SELECTまたはIL1別に

を持つことができます:

かかわらず、あなたがやっていると思うか、何をしたいのかの
  • ロックが自動的に行われ、そしてISOLATION LEVEL 3以来、あなたがそれらを使用している場合、サーバーは彼らに
  • を無視し、READ UNCOMMITTEDNOLOCKは適用されませんし、使用することはできませんここで、UPDATESDELETESためを必要とします
+1

あなただけがこの方法でより頻繁に答えたら... +1 – gbn

関連する問題