2012-03-23 81 views
5

我有一張從視圖中填充的大表格。這樣做是因爲視圖需要很長時間才能運行,並且數據很容易在表中使用。每隔一段時間運行一次程序以更新表格。插入時鎖定表格

TRUNCATE TABLE LargeTable 

INSERT INTO LargeTable 
SELECT * 
FROM viewLargeView 
WITH (HOLDLOCK) 

我想在插入時鎖定此表,所以如果有人試圖選擇一條記錄,截斷後他們將不會收到任何記錄。我正在使用的鎖似乎鎖定了視圖而不是表格。

有沒有更好的方法來解決這個問題?

+1

在插入和關閉之後打開一個事務怎麼樣? – 2012-03-23 15:51:33

+0

當打開一個事務時,另一個用戶可以從表中選擇? – JBone 2012-03-23 15:57:07

+0

僅供參考,我建議您使用DELETE而不是TRUNCATE,因爲TRUNCATE是DDL,而不是像DELETE這樣的DML,因此需要更大的權限。另外,如果你在交易中(這是你的問題的正確答案)包裝這些,他們將有效地執行相同的操作。 – RBarryYoung 2012-03-23 16:02:34

回答

4
BEGIN TRANSACTION t_Transaction 

BEGIN TRY 

TRUNCATE TABLE LargeTable 

INSERT INTO LargeTable 
SELECT * 
FROM viewLargeView 
    WITH (HOLDLOCK) 


COMMIT t_Transaction 

END TRY 

BEGIN CATCH 
    ROLLBACK t_Transaction 
END CATCH 
+0

不要以爲這會做任何事情。 「truncate」不受事務影響,即使沒有指定一個,它本身也是一個事務。 – Andomar 2012-03-23 16:08:45

+0

其實TRUNCATEs回滾有一些警告。見[this](http://blog.sqlauthority.com/2007/12/26/sql-server-truncate-cant-be-rolled-back-using-log-files-after-transaction-session-is-closed /) – 2013-08-16 15:47:00

4

確實,您正確的鎖定提示會影響源視圖。

爲了讓這個沒有人可以從表中讀取,當你插入:

insert into LargeTable with (tablockx) 
... 

你不必做任何事情來使表看空,直至插入完成後。插入始終在事務中運行,除非它們明確指定了with (nolock)set transaction isolation level read uncommitted,否則其他進程不能讀取未提交的行。就我所知,沒有辦法保護這一點。