mssql how to get lock on whole table without select statement? - sql-server-2005

MSSQL 2005 .I want to get a lock on a table at the start of transaction and only release it at the end of the transaction
BEGIN TRANSACTION;
-- get lock
BEGIN TRY
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0 BEGIN
ROLLBACK TRANSACTION;
-- release lock
END
END CATCH;
IF ##TRANCOUNT > 0 BEGIN
COMMIT TRANSACTION;
-- release lock
END
GO
Does lock on table gets automatically released once transaction has completed or rolledback?

Table locks, or other types of locks, can be set using hints like so:
UPDATE Users WITH (TABLOCK) SET Username = 'fred' WHERE Username = 'foobar'
Locks will generally expire when the command completes (even if the transaction is not yet done), unless you add other hints to keep them around within the scope of the transaction. See http://msdn.microsoft.com/en-us/library/ms187373%28v=sql.90%29.aspx for an explanation of all lock types and other table hints.
Locks will affect other users depending on the isolation level of their own transactions. See http://msdn.microsoft.com/en-us/library/ms173763%28v=sql.90%29.aspx for more info.

Related

Is it possible for parent transaction to fail if nested transaction was successfully committed

I'm trying to understand nested transactions in SQL Server. Lets consider following chain for SQL commands:
BEGIN TRANSACTION; -- #1
BEGIN TRANSACTION; -- #2
UPDATE foo SET column = 'something'; -- Change something in one table.
COMMIT TRANSACTION; -- #2
If commit of transaction #2 succeed is it possible for commit of transaction #1 to fail? If yes, could you provide an example when this might happen?
From A SQL Server DBA myth a day: (26/30) nested transactions are real:
The commit of a nested transaction has absolutely no effect – as the only transaction that really exists as far as SQL Server is concerned is the outer one. ...
The rollback of a nested transaction rolls back the entire set of transactions – as there is no such thing as a nested transaction.
SELECT ##TRANCOUNT;
BEGIN TRANSACTION; -- #1
SELECT ##TRANCOUNT;
BEGIN TRANSACTION; -- #2
SELECT ##TRANCOUNT;
UPDATE foo SET [column] = 'something';
COMMIT TRANSACTION; -- #2
SELECT ##TRANCOUNT;
ROLLBACK; -- simulate error or explicit rollback
-- update is lost
DBFiddle Demo
If you want something like Oracle autonomous transaction please read: Commit transaction outside the current transaction (like autonomous transaction in Oracle)

How can I check whether a stored procedure that deletes all rows from multiple tables succeeded?

I want a stored procedure that does the equivalent of the following
CREATE PROCEDURE Reset
AS
BEGIN
DELETE * FROM SomeTable;
DELETE * FROM SomeOtherTable;
END
and also returns some indicator of success or failure. How would I do that? Only way I can think of is pre-calculating the number of rows that should be affected, but that seems so shoddy.
The following will produce a success/failure indicator based on the question, 'did the table reset complete without failure?'. It's wrapped in a transaction so that both deletes happen or none happen, which keeps your data clean.
BEGIN TRY
BEGIN TRANSACTION;
DELETE FROM SomeTable;
DELETE FROM SomeOtherTable;
COMMIT TRANSACTION;
-- success indicator
SELECT 1 AS Result
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRANSACTION;
-- failure indicator
SELECT 0 AS Result
END CATCH

Inner rollback transaction rolls back the outer too

I faced a problem like this. I have this transaction, and $(FilePath) specifies another script, that this should start running.
BEGIN TRANSACTION
:r $(FilePath)
GO
IF(##ERROR <> 0)
BEGIN
ROLLBACK TRANSACTION
END
ELSE
BEGIN
COMMIT TRANSACTION
END
(Note that the scripts that are called by the sqlcmd mostly doesn't contain transacions)
The problem is that, if the script that is being called contains a rollback transaction then it rolls back the outer transaction too. The inner scripts doesn't contain named transactions, and there are way too many scripts to rewrite each transaction to be named.
Is there a way to make this transaction only roll back if the corresponding rollback transaction runs?
Thank you
Try using a savepoint_name with your ROLLBACK statement like described here:
Without this savepoint the ROLLBACK statement rolls back transactions to the outermost BEGIN TRANSACTION statement as designed.
ROLLBACK { TRAN | TRANSACTION }
[ transaction_name | #tran_name_variable
| savepoint_name | #savepoint_variable ]
[ ; ]
ROLLBACK TRANSACTION without a savepoint_name or transaction_name
rolls back to the beginning of the transaction. When nesting
transactions, this same statement rolls back all inner transactions to
the outermost BEGIN TRANSACTION statement. In both cases, ROLLBACK
TRANSACTION decrements the ##TRANCOUNT system function to 0. ROLLBACK
TRANSACTION savepoint_name does not decrement ##TRANCOUNT.

Can there be multiple commits to one transaction regardless of scope of while loop

Following is a SQL Server stored procedure. There is on start of transaction and there are two commits as you can see below. Is this valid (start is in while loop and 1st commit is in same while loop, but 2nd commit is in 2nd while loop)? If not what could be the solution to do it?
Please help.
IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'DELETE_COBOC_DATA')
DROP PROCEDURE DELETE_COBOC_DATA
GO
CREATE PROCEDURE DELETE_COBOC_DATA #ORGDN VARCHAR(100), #CHUNK VARCHAR(10)
AS
BEGIN
-- some code that executes before while
WHILE (#NUM_ROWS_TMPTRADMIN > 0)
BEGIN
BEGIN TRANSACTION
-- executes some code
COMMIT TRANSACTION
END
-- some more code
WHILE #NUM_ROWS_TMPDIR > 0
BEGIN
-- code code code
COMMIT TRANSACTION
-- code code code
END
-- some more code here as well
END
As I know this is allowed in MySQL
You cannot commit the same transaction twice. You can have nested transactions, but you cannot have "partial" commits, that is contradictory to the notion of a transaction (it's all-or-nothing). If both commits are executed, the second one will throw an error
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION

SQL Server BEGIN/END vs BEGIN TRANS/COMMIT/ROLLBACK

I have been trying to find info on the web about the differences between these statements, and it seems to me they are identical but I can't find confirmation of that or any kind of comparison between the two.
What is the difference between doing this:
BEGIN
-- Some update, insert, set statements
END
and doing this
BEGIN TRANS
-- Some update, insert, set statements
COMMIT TRANS
?
Note that there is only the need to rollback in the case of some exception or timeout or other general failure, there would not be a conditional reason to rollback.
BEGIN and END deal with code blocks. They are similar to the curly braces you see in many languages:
if (somethingIsTrue)
{ // like BEGIN
// do something here
} // like END
In SQL, this is:
if somethingIsTrue
BEGIN
-- do something here
END
BEGIN TRAN, COMMIT, and ROLLBACK begin and end transactions. They do not specify a new block of code; they only mark the transaction boundaries.
Note that you can write a BEGIN TRAN and COMMIT in separate blocks of code. For example, if you want code to be part of a transaction, but you don't want to start a new one if the code is already in a transaction, you can do something like this:
declare #TranStarted bit = 0
if ##trancount = 0
begin
set #TranStarted = 1
begin tran
end
-- ... do work ...
if #TranStarted = 1
begin
commit
set #TranStarted = 0
end
The regular BEGIN and END are not used for transactions. Instead, they are just for indicating that some block of code is a single unit, much like braces {} in C#/C++/Java.
If you have an IF statement or a WHILE loop that does 10 things, you need to enclose them in BEGIN/END so that SQL Server knows that that whole list of 10 statements should be executed as a part of that condition.
These 2 statements are entirely different.
BEGIN..END mark a block of code, eg in an if statement
IF #something = 1
BEGIN
-- Do something when #something is equal to 1
END
BEGIN TRANS..COMMIT TRANS wrap the enclosing block in a transaction, and depending on server settings will rollback the transaction if an error occurs.
It should be mentioned, that there is a Begin; in PostgreSQL, that also initiates a transaction block, which at first confused me.
http://www.postgresql.org/docs/9.0/static/sql-begin.html
"BEGIN initiates a transaction block, that is, all statements after a BEGIN command will be executed in a single transaction until an explicit COMMIT or ROLLBACK is given. By default (without BEGIN), PostgreSQL executes transactions in "autocommit" mode, that is, each statement is executed in its own transaction and a commit is implicitly performed at the end of the statement (if execution was successful, otherwise a rollback is done)."
I have not seen END TRANS
:)
i think we use END only for BEGIN keyword not for BEGIN trans
we use commit or rollback for BEGIN trans