SQL Server 2005 and SELECT and UPDATE locked - sql

I want to perform a update then select the result. I don't want anything to be able to update the row I am updating until after the select has occurred. How would I do this?
My goal is to increment a value of a row and return that incremented value. I have thus far found that I end up with an issue where update (to increment) followed by a select in a situation where two queries happen at near the same time the selects seem to return the same number. So I am guessing that something like update > update > select > select is happening.
I miss labeled this as SQL Server 2005. I am actually working with Server 2000. So the output clause does not work (is not in that version).
BEGIN TRANSACTION
UPDATE Table SET Last=(Last+1) WHERE ID=someid;
SELECT * FROM Table WHERE ID=someid;
COMMIT TRANSACTION

BEGIN TRAN
UPDATE ...
SELECT...
COMMIT
Should do it even at the default transaction isolation level of read committed.
You could also use the OUTPUT clause to get the row directly back after the update. Example of this
UPDATE <YourTable>
SET ...
OUTPUT INSERTED.*
WHERE ...

Related

Can an updated with nested select be considered atomic in Sybase?

I am trying something like this:
set rowcount 10 //fetch only 10 row
Update tableX set x=#BatchId where id in (select id from tableX where x=0)
basically mark 10 record as booked by supplying a batchId.
So my question is if this proc is executed in parallel then can I guarantee that update with select will be atomic and no invocation will select similar setof record from tableX for booking?
Thanks
To guarantee that no such overlaps occur, yo should:
(i) put BEGIN TRANSACTION - COMMIT around the statement
(ii) put the HOLDLOCK keyword directly behind 'tableX' (or run the whole statement at isolation level 3).

Atomic update column in SQL Server

I am using MS SQL Server, and I have a table. I want each SQL Server client to acquire one row and update it, so that the client knows that only he acquired that record, and no one else!
record1 a b c 0
record2 d e f 0
...
One client should acquire and update last value from 0 to 1.
The solution should work at least from SQL Server 2005 and above.
ATOMIC
{
select top 1 * from table where column='0' // get one row where column is '0'
update table set column='1'
}
You could do something like:
update top (1) table with (readpast)
set Column1=1
output inserted.*
where Column1 = 0
Which should do it all in one go. You only need the readpast hint if, having acquired the unique value, the connection keeps a transaction open for a long period of time. If you're just doing the update you can omit it.
You can update a table through a Common Table Expression.
Below I create a CTE that picks just one row and then that is used in the UPDATE.
WITH
singleRow AS
(
select top 1 * from table where column='0'
)
UPDATE
singleRow
SET
column= '1'
;
NOTE: Remember to ensure any preceding commands are terminated with a ;, else the WITH syntax doesn't work.

lock a table in sql server 2008 after select

I have a main currency table. Which has two fields, one currency Type and currency value. User can not be changed once a user start working with the DB. I need to lock my Currency table through SQL Server 2008 Query once user select one value.
Can any one help me or suggest me for DB LOCK query.
We had the same problem on a table in our database. Found this and it worked for us:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
SELECT * FROM dbo.MyTable WITH (TABLOCKX);
The table will be locked until a COMMIT TRANSACTION or ROLLBACK TRANSACTION is executed.
Hope it helps somebody in the future...
You can use NOLOCK for your objects.
For example :
SELECT TOP 10 * FROM Orders WITH(NOLOCK) where UserName = 'VadaVici'

how to know how many rows will be affected before running a query in microsoft sql server 2008

i've read a bit about ROWCOUNT but its not exactly what im looking for. from my understanding rowcount states the number of rows affected AFTER you run the query. what im looking for is knowing BEFORE you run the query. is this possible?
You can also use BEGIN TRANSACTION before the operation is executed. You can see the number of rows affected. From there, either COMMIT the results or use ROLLBACK to put the data back in the original state.
BEGIN TRANSACTION;
UPDATE table
SET col = 'something'
WHERE col2 = 'something else';
Review changed data and then:
COMMIT;
or
ROLLBACK;
Short answer is no..
You cannot get the number of rows before executing the query..atleast in SQL server.
The best way to do it is use
Select count(*) from <table> where <condtion>
then execute your actual query
[delete]or [update] [set col='val']
from <table> where <condtion>
The estimated execution plan is going to give you rows affected based on statistics, so it won't really help you in this case.
What I would recommend is copying your UPDATE statement or DELETE statement and turning it into a SELECT. Run that to see how many rows come back and you have your answer to how many rows would have been updated or deleted.
Eg:
UPDATE t
SET t.Value = 'Something'
FROM MyTable t
WHERE t.OtherValue = 'Something Else'
becomes:
SELECT COUNT(*)
FROM MyTable t
WHERE t.OtherValue = 'Something Else'
Simplest solution is to replace the columns in the SELECT * FROM... with SELECT Count(*) FROM ... and the rest of your query(the WHERE clause needs to be the same) before you run it. This will tell you how many rows will be affected
The simplest solution doesn't seem to work in a case where theres a subquery. How would you select count(*) of this update:
BEGIN TRANSACTION;
update Table1 t1 set t1.column = t2.column
from (
SELECT column from Table2 t2
) AA
where t1.[Identity] = t2.[Identity]
COMMIT;
Here I think you need the BEGIN TRANSACTION

Rollback the changes for Update Query

UPDATE UPI_ATTRIBUTE SET SITE_INC ='0'
WHERE USER_PROFILING_NAME IN ('CAR_IMPLICIT','CAR_EXPLICIT')
Above is my query that I am using to update the columns in UPI_ATTRIBUTE table. And suppose if I need to rollback the above changes that I am doing with update query, then how can I use the delete query in the above case? Currently SITE_INC is empty. So after updating the table it will have 0 in that. And If I need to rollback the changes then I need to make it empty again.
How can I delete the value 0 from above column after updating.
You cannot "delete" data to rollback an update.
Even if the only change that you'll do is set a flag from "NULL" to "Y" and vice versa, you can't really determine which value to update when you do multiple updates.
update 1 : set from "NULL" to "0"
update 2 : set from "0" to "something else"
update 3 : Rollback changes (rollback to which state)?
If you want to really rollback changes to specific rows (instead of the complete table, which can be done using Flashback), you can audit the changes to "remember" the values and then revert back to them.
Even then, you should consider which point to revert to, when you have multiple updates.
Not sure Oracle have final table/old table function for select/update.
For DB2 for z/OS, it have such function:
SELECT LASTNAME, BONUS FROM FINAL TABLE
(UPDATE EMP SET BONUS = BONUS * 1.3
WHERE JOB = 'CLERK');
Then, the result set of the select include all the updated rows. you can use rownum or other unique value, then you can update it back to any value as you want.