Brenda,
So, once the transaction(cursor\proc) starts- there should not be any insert or update to table data?
That means you need take an exclusive lock on the table and hold it till your transaction completes.
so, the obvious downside, you are preventing other transactions to access the data(without nolocks)\insert\update and doing the transaction though cursor, makes it worse because, cursor(loops) generally tend to be slow.
also, is it really required not to have any changes(new\update) made to the table while the job is running?
there are other isolation levels(read committed snapshot,read committed,repeatable read) that provide can you better concurrency and yet always only -committed data. read committed snapshot provides better at this - allows other applications make changes
and at the same time lets you read the new committed data without blocking.
but, to acheive what you said(or what i understood) is possible but in most cases, not a good way.
to acheive what you said, you need either - serializable isloation level or take exculsive lock. exuclsive lock, takes complete control on the table where as in serializable, it takes control on the data, so it allows new\update on the data that is outside
of the cursor select data set range..
try this example with exculsive lock :
--session 1
Drop table test
go
create table test(sno int primary key,sname varchar(20))
go
insert into test values(1,'stan'),(2,'william')
go
Begin Tran
declare @sno int
declare @sname varchar(20)
DECLARE db_cursor CURSOR FOR
SELECT sname,sno
FROM dbo.test with (Tablockx)
where sno<=2
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @sname,@sno
WHILE @@FETCH_STATUS = 0
BEGIN
select @sno,@sname
waitfor delay '00:00:05'
FETCH NEXT FROM db_cursor INTO @sname,@sno
END
CLOSE db_cursor
DEALLOCATE db_cursor
commit
---Session 2
insert into test values(3,'nathan')
try this example with serializable isolation
Drop table test
go
create table test(sno int primary key,sname varchar(20))
go
insert into test values(1,'stan'),(2,'william')
go
Set Transaction Isolation Level Serializable
Begin Tran
declare @sno int
declare @sname varchar(20)
DECLARE db_cursor CURSOR FOR
SELECT sname,sno
FROM dbo.test
where sno<=2
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @sname,@sno
WHILE @@FETCH_STATUS = 0
BEGIN
select @sno,@sname
waitfor delay '00:00:05'
FETCH NEXT FROM db_cursor INTO @sname,@sno
END
CLOSE db_cursor
DEALLOCATE db_cursor
Commit
--session 2. will wait till session 1 is finished
update test set sname='qaz' where sno=2
--session 3 - will insert, since the data range falls outside the cursoe data set.
insert into test values(3,'nathan')