I have a statement with a single UPDATE command. If I manually terminate it will all the results be rolled back?
If you kill the connection on which the update was issued, or otherwise manage to cancel the query, the update will be rolled back. Every DML statement in SQL runs within the context of a transaction - SQL Server will automatically create one if one doesn't exist, and commit it after the statement completes.
If no errors occur then this statement cannot be rolled back
Update table
Set MyCol = 'foo'
Where MyOtherCol = 'bar'
However, what you can do in SQL is run the following statements together:
begin transaction
Update table
Set MyCol = 'foo'
Where MyOtherCol = 'bar'
Then perform any checks that you may need to do. If everything is ok then you can run the following.
commit transaction
if you need to cancel the update you can run this
rollback transaction
Related
If a stored procedure contains multiple statements e.g. first an insert, then an update and finally a deletes and the stored procedure gets killed in the middle of the delete, does the insert and update also have to be rolled back? Or does it only roll back the delete i.e. the implicit transaction?
As explained in Transactions, each statement will be executed as an implicit transaction. If a statement fails then the effect of prior statements will remain committed.
Note that the entire stored procedure may be executed within an explicit transaction created by the calling code.
insert and update have to be commited but delete Statement was rolled back
since you have no explicit BEGIN TRANSACTION in the stored procedure, each statement will run on its own with no ability to rollback any changes if there is an error.
However, if before you call the stored procedure you issue a BEGIN TRANSACTION, then all statements are grouped within a transaction and can either be COMMITted or ROLLBACKed following stored procedure execution.
Reference: KM.
How does SQL Server treat statements inside stored procedures with respect to transactions?
I have a chunk of SQL code that has the following format:
SET IMPLICIT_TRANSACTIONS ON
// Insert or Update Statement #1
GO
// Insert or Update Statement #2
GO
IF ##TRANCOUNT > 0 COMMIT TRAN
SET IMPLICIT_TRANSACTIONS OFF
My question: is statement 1 in the same transaction as statement 2 (but that they are in different batches)? I'd believe so based on my reading on Google but I'd like some second opinions.
Thanks!
It depends.
If the both statements are either one of the following :
ALTER TABLE
FETCH
REVOKE
BEGIN TRANSACTION
GRANT
SELECT
CREATE
INSERT
TRUNCATE TABLE
DELETE
OPEN
UPDATE
DROP
then the answer is yes.
Because if the connection is already in an open transaction, the above statements do not start a new transaction.
If, however, Statement 2 is BEGIN TRANSACTION then it will cause two nested transactions to open.
http://msdn.microsoft.com/en-us/library/ms187807(v=sql.100).aspx
And the GO command is just a batch separator , it doesn't start a new transaction.
A transaction can be wrapped around multiple batches.
I've got a simple SQL command that is supposed to read all of the records in from a table and then delete them all. Because there's a chance someone else could be writing to this table at the exact moment, I want to lock the table so that I'm sure that everything I delete is also everything I read.
BEGIN TRAN T1;
SELECT LotID FROM fsScannerIOInvalidCachedLots WITH (TABLOCK, HOLDLOCK);
DELETE FROM fsInvalidCachedLots;
COMMIT TRAN T1;
The really strange thing is, this USED to work. It worked for a while through testing, but now I guess something has changed because it's reading everything in, but it's not deleting any of the records. Consequently, SQL Server is spinning up high CPU usage because when this runs the next time it takes significantly longer to execute, which I assume has something to do with the lock.
Any idea what could be going on here? I've tried both TABLOCK and TABLOCKX
Update: Oh yea, something I forgot to mention, I can't query that table until after the next read the program does. What I mean is, after that statement is executed in code (and the command and connection are disposed of) if I try to query that table from within Management Studio it just hangs, which I assume means it's still locked. But then if I step through the calling program until I hit the next database connection, the moment after the first read the table is no longer locked.
Your SELECT retrieves data from a table named fsScannerIOInvalidCachedLots, but the delete is from a different table named fsInvalidCachedLots.
If you run this query in set xact_abort off, the transaction will not be aborted by the error from the invalid table name. In fact, select ##trancount will show you that there is an active transaction, and select xact_state() will return 1 meaning that it is active and no error has occurred.
On the other hand, with set xact_abort on, the transaction is aborted. select ##trancount will return 0, and select xact_state() will return 0 (no active transaction).
See ##trancount and xact_state() on MSDN for more information about them.
Does a rollback inside a INSERT AFTER or an UPDATE AFTER trigger rollback the entire transaction or just the current row that is the reason for trigger, and is it same with Commit ?
I tried to check it through my current projects code which uses MSTDC for transactions, and it appears as if though the complete transaction is aborted.
If a Rollback in the trigger does rollback the entire transaction, is there a workaround for to restrict it just the current rows.
I found a link for sybase on this, but nothing on sql server
Yes it will rollback the entire transaction.
It's all in the docs (see Remarks). Note the comment I've emphasised - that's pretty important I would say!!
If a ROLLBACK TRANSACTION is issued in a trigger:
All data modifications made to that point in the current transaction
are rolled back, including any made by the trigger.
The trigger continues executing any remaining statements after the
ROLLBACK statement. If any of these statements modify data, the
modifications are not rolled back. No nested triggers are fired by the
execution of these remaining statements.
The statements in the batch after the statement that fired the trigger
are not executed.
As you've already been let to know, the ROLLBACK command can't possibly be modified/tuned so that it only roll back the statements issued by the trigger.
If you do need a way to "rollback" actions performed by the trigger only, you could,
as a workaround, consider modifying your trigger in such a way that before performing the actions, the trigger makes sure those actions do not produce exceptional situations that would cause the entire transaction to rollback.
For instance, if your trigger inserts rows, add a check to make sure the new rows do not violate e.g. unique constraints (or foreign key constraints), something like this:
IF NOT EXISTS (
SELECT *
FROM TableA
WHERE … /* a condition to test if a row or rows you are about
to insert aren't going to violate any constraint */
)
BEGIN
INSERT INTO TableA …
END;
Or, if your trigger deletes rows, check if it doesn't attempt to delete rows referenced by other tables (in which case you typically need to know beforehand which tables might reference the rows):
IF NOT EXISTS (
SELECT * FROM TableB WHERE …
)
AND NOT EXISTS (
SELECT * FROM TableC WHERE …
)
AND …
BEGIN
DELETE FROM TableA WHERE …
END
Similarly, you'd need to make checks for update statements, if any.
Any rollback command will roll back everything till the ##trancount is 0 unless you specify some savepoints and it doesnt matter where you put rollback tran command.
The best way is to look into the code once again and confirm business requirement and see why do you need a rollback in trigger?
at most pages I have read that "DDL commands have AutoCommit in SQL Server", if I am not wrong this statement simply means that we don't need explicit commit command for DDL commands.
then why...
1) Alter TABLE EMP Add Age INT;
UPDATE EMP SET Age=20;
fails ,saying Invalid column name 'Age'
2) BEGIN TRAN
Alter TABLE EMP Add Age INT;
ROLLBACK
can be rollbacked successfully.
Maybe I am wrong with concept of AutoCommit, please explain it with example where it actully has effects.
Thanks for any help.
Autocommit Transactions:
A connection to an instance of the Database Engine operates in autocommit mode until a BEGIN TRANSACTION statement starts...
So, your second example doesn't apply. Further down:
In autocommit mode, it sometimes appears as if an instance of the Database Engine has rolled back an entire batch instead of just one SQL statement. This happens if the error encountered is a compile error, not a run-time error. A compile error prevents the Database Engine from building an execution plan, so nothing in the batch is executed.
Which is what your first example deals with.
So, neither one is actually dealing with Autocommit transactions.
So, lets take a statement like:
Alter TABLE EMP Add Age INT;
If you have an open connection in Autocommit mode, execute the above, and it completes without errors, then you will find that this connection has no open transactions, and the changes are visible to any other connection immediately.
If you have an open connection in Implicit Transactions mode, execute the above, and it completes without errors, then you will find that this connection has an open transaction. Other connections will be blocked on any operations that require a schema lock on EMP, until you execute either COMMIT or ROLLBACK.
If you have an open connection, in which you have executed BEGIN TRANSACTION, execute the above, and it completes without errors - then you'll be in the same situation as for Implicit Transactions. However, having COMMITed or ROLLBACKed, your connection will revert to either Autocommit mode or Implicit Transactions mode (whichever was active before the call to BEGIN TRANSACTION).
If you have a begin tran explicitly like in your second example, then you have to commit it. (you can roll back as well)
If you dont specify it explicity like in your first example then it is autocommit.
autocommit is the default mode in sql server, which can be turned off if requried
If you add batch in your code it will work
Alter TABLE EMP Add Age INT;
go
UPDATE EMP SET Age=20;