lock a table in sql server 2008 after select - sql

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'

Related

SQL Server - Non-distributed transaction over two DBs

I am trying to localize an issue I have
with 2 DBs and their transactional behavior.
I create two DBs on a single SQL Server 2008 R2 instance.
test1
test2
test1 has one table Table_1
test2 has one table Table_2
Both tables have an ID (int) and a value (string) columns.
Both have just one row which has ID=1.
Then in SQL Server Management Studio,
in some window 1 I do
use test1
begin transaction
update test1.dbo.Table_1
set
value = 'TEST-100'
where
ID = 1
update test2.dbo.Table_2
set
value = 'TEST-200'
where
ID = 1
commit transaction --- but I don’t run the commit yet ---
and then in another window 2, I do
select * From test1.dbo.Table_1
with (nolock)
select * From test2.dbo.Table_2
with (nolock)
This way I can see the two uncommitted yet values.
But if in window 2, I do
select * From test1.dbo.Table_1
or
select * From test2.dbo.Table_2
these SELECT staments hang.
So my question is: is that transaction from
window 1, spanning two DBs? Seems so because
select * From test2.dbo.Table_2
hangs too which means to me that test2.dbo.Table_2
is enlisted in the same transaction which I started
in window 1.
But why is this transaction acting like a distributed one?
Is that normal? What is the explanation? Is that some
undocummented feature in SQL Server? Are there any
references which would explain that behavior I am seeing?
When a query spans over 2 databases, then your transaction is promoted to a distributed transaction handled by MSDTC. It's the normal way to be and it happens without explicitly using BEGIN DISTRIBUTED TRANSACTION statement.

If statement on update statement Instead of trigger?

I have a stored procedure where I will calculate factors by merging some tables and updates in table 'tablea'. I have created a trigger on tablea so when there is a update those records will entered into new table 'tablea_new'. My problem with trigger is I will have 6 months factors updated at a time but they some months factors may not updated but they should entered in to new table.So trigger troubled me a lot.
So I went with an If statement to insert update records
My code for If statement is
#Action A
SET A.Factor=B.Net/B.Cost,A.Net=B.Net,A.LastModified=sysDatetime(),A.LastModifiedBy=suser_name(),A.Path=B.Path
FROM Tablea A
INNER JOIN ##TEMP3 B ON
A.Year=B.Year AND
A.Month=B.Month AND
A.Media=B.Media
IF #Action='UPDATE'
BEGIN
INSERT INTO Tablea_New (ID,Media,Year,Month,Factor,Net,UpdatedDate,UpdatedBy,FilePath)
SELECT ID,Media,Year,Month,Factor,Net,LastModified,LastModifiedBy,FilePath FROM Tablea
WHERE Media='CNN'AND YEAR=#YEAR AND Net >1
END
Can you guys give me some suggestions is there can I make some modifications or I need to use triggers :(
You can make use of the Change Data Capture (CDC) feature in SQL Server 2008 R2. This will help you to automatically store all changed rows, irrespective of the type of change (i.e. whether it is insert, update or delete).
To enable CDC for your database, use the below script
USE your_database_name
GO
EXEC sys.sp_cdc_enable_db
To enable CDC for your table, use the below script
EXEC SYS.sp_cdc_enable_table
#source_schema = N'your_schema_name',
#source_name = N'your_table_name',
#role_name = NULL
Once CDC is enabled, a new table is created under schema 'cdc' to store the changed rows, along with metadata about the change. You may directly access this table to get the required data.

SQL Query Execution more than once?

I have 2 tables (A,B), and 1 query
My query is something like this
Read From A
Update B with this data from A
Using the updated table B, set final value of A.
Example execution can be find in below question:
Proper way to keep a single data in sql server?
Now since all the process is connected, this query should not be executed twice at the same time, or by 2 different users until the process ends. How do I prevent this ? Or does it already work securely like this?
Use transaction lock :
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
BEGIN TRANSACTION
--select * from A
-- update B ....
--update A
WAITFOR DELAY '00:00:02' -- tables remain locked for 2 secs hh:mm:ss
commit TRANSACTION
during the transaction execution, any try to read or write from/to tables will timeout...
EDIT :
u must use, some lock to lock the db while updating. http://msdn.microsoft.com/en-us/library/ms173763.aspx
psedo code for u:
int x=(select val from tableB)+1
query="update tableB set tableB.field="+x+"where......."
if query executed successfully:
update tableA
I hope that your table A and B must be having some Primary Key eg EmployeeID. In such case a simple solution is to create a table (say Lock_Table) which keeps a record of the EmployeeID beign modified.
So here you would need to go like this:
BEGIN TRANSACTION
1- Read EmployeeID From A
2- Check if EmployeeID already exists in Lock_Table. If Yes then Quit Else insert that EmployeeID in Lock_Table
3- Update B with this data(EmployeeID in this case) from A
4- Using the updated table B, set final value of A.
5- Delete this EmployeeID from the Lock_Table
COMMIT TRANSACTION
On any error ROLLBACK the Transaction.
Hope it helps.

can't insert records in new table from existing table in sql server 2005

I need to insert records into a new table from an existing table. I used the following query to do this:
Insert into Newtable
Select * from Oldtable where date1 = #date
This query works most of the time, but in one scenario I get 10 million records to be inserted for the date1 value. In this case I'm getting the following error message:
Error : The transaction log for database "tempDB" is full. To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sys.databases
Should I break the query into parts and insert them sequentially, or is there a way to do this with the current query?
This is, perhaps, a distasteful suggestion. But, you can try exporting the data to a file and then inserting using bulk-insert, with database logging set to SIMPLE or BULK-LOGGED.
More information is at http://msdn.microsoft.com/en-us/library/ms190422.aspx.

SQL Server 2005 and SELECT and UPDATE locked

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 ...