2012-03-23 84 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,否则其他进程不能读取未提交的行。就我所知,没有办法保护这一点。