Does autocommit in postgresql mean you cannot have transaction blocks? - sql

if autocommit is on, which is default, postgresql treats each statement as a transaction.
so if i have an explicit transaction block with start transaction and commit, does that mean that block is not executed atomically and cannot be rolled back? (since each statement inside the block would be a transaction in itself due to autocommit).

It's the opposite.
With autocommit turned on, using start transaction is the only way to combine multiple statements into a single transaction.
In fact, Postgres always uses autocommit on the server, unless the client uses start transaction (or begin transaction). When you turn off auto-commit the client will simply send those statements for you automatically.
Quote from the manual
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
(Emphasis mine)
BEGIN is the same as START TRANSACTION

Autocommit only affects statements outside of a transaciton. When you do your own start transaction and commit, autocommit has no effect.
When a statement is run outside a transaction, autocommit
ON means that means it is committed when it finishes
OFF means that a new transaction is implicitly started, and an explicit commit is required to commit the statement

Related

Uncommitted transaction asking every time in SQL Server 2012

I am facing issues like whenever I open SQL windows and run any SQL transaction (insert, update or delete or any modification in procedure), it asks about uncommitted transaction.
How to fix this permanently?
Sounds like you probably have SET IMPLICIT_TRANSACTIONS on.
This will open a new transaction implicitly when it encounters statements such as insert, update or delete and no transaction is open and will require an explicit commit or rollback.
Implicit transactions may unexpectedly be ON due to ANSI defaults. For details see SET ANSI_DEFAULTS (Transact-SQL).
IMPLICIT_TRANSACTIONS ON is not popular. In most cases where IMPLICIT_TRANSACTIONS is ON, it is because the choice of SET ANSI_DEFAULTS ON has been made.
You need to go into the connection properties and ensure you have not enabled implicit transactions either explicitly or implicitly.
When you use BEGIN TRANSACTION you also need to either COMMIT TRANSACTION if it has done all the work you want correctly or ROLLBACK TRANSACTION if there has been issues and you want to return to the state before the start of the transaction.
Read up on transactions here

Where is the flaw in my trigger to override DELETE with a soft-delete?

I have a trigger created with
CREATE TRIGGER [CantDeleteStuff] ON [dbo].[Stuff]
INSTEAD OF DELETE
AS
BEGIN
ROLLBACK
UPDATE [dbo].[Stuff] SET [Deleted]=1 FROM DELETED WHERE [dbo].[Stuff].[Id] = DELETED.[Id]
END
GO
and I think it's intent is clear. But when I try to delete a row I get the error
The transaction ended in the trigger. The batch has been aborted.
How to fix?
Instead of Delete will replace the Delete with your triggering code.
According to Technet, the Rollback in your trigger is the issue. You can read more here.
A trigger operates as if there were an outstanding transaction in effect when the trigger is executed. This is true whether the statement firing the trigger is in an implicit or explicit transaction.
When a statement begins executing in autocommit mode, there is an implied BEGIN TRANSACTION to allow the recovery of all modifications generated by the statement if it encounters an error. This implied transaction has no effect on the other statements in the batch because it is either committed or rolled back when the statement completes. This implied transaction is still in effect, however, when a trigger is called.
When a trigger executes, an implicit transaction is started. If the trigger completes execution and ##TRANCOUNT = 0, error 3609 occurs and the batch is terminated. If a BEGIN TRANSACTION statement is issued in a trigger, it creates a nested transaction. In this situation, when a COMMIT TRANSACTION statement is executed, the statement will apply only to the nested transaction.
When using ROLLBACK TRANSACTION in a trigger, be aware of the following behavior:
All data modifications made to that point in the current transaction are rolled back, including any that were 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.
A ROLLBACK in a trigger closes and deallocates all cursors that were declared and opened in the batch containing the statement that fired the trigger. This includes cursors declared and opened in stored procedures called by the batch that fired the trigger. Cursors declared in a batch prior to the batch that fired the trigger are only closed. However, STATIC or INSENSITIVE cursors are left open if:
CURSOR_CLOSE_ON_COMMIT is set OFF.
The static cursor is either synchronous or a fully populated asynchronous cursor.
Instead of using ROLLBACK TRANSACTION, the SAVE TRANSACTION statement can be used to execute a partial rollback in a trigger.
https://technet.microsoft.com/en-us/library/ms187844(v=sql.105).aspx
So just remove the Rollback.

Does "set transaction" start a transaction when autocommit is ON?

I am using Oracle with AutoCommit ON mode (Java Application using JDBC).
When I execute multiple DML statements as a single transaction, I thought I could do something like this:
set transaction read write
update user_tbl set name='mark' where email='m#xyz.com'
update user_tbl set name='ken' where email='k#xyz.com'
--if other things are successful, then:
commit
-- else:
--rollback
However it appears that, whenever I do end up executing rollback, the rows have the new values given my above statements.
So, even though set transaction was executed at the beginning, is it possible that update statements are being executed in AutoCommit ON mode?
This is clearly explained in the documentaton:
http://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html
http://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html#setAutoCommit(boolean)
Note: When configuring a Connection, JDBC applications should use the appropriate Connection method such as setAutoCommit or setTransactionIsolation. Applications should not invoke SQL commands directly to change the connection's configuration when there is a JDBC method available. By default a Connection object is in auto-commit mode, which means that it automatically commits changes after executing each statement. If auto-commit mode has been disabled, the method commit must be called explicitly in order to commit changes; otherwise, database changes will not be saved.
setAutoCommit
void setAutoCommit(boolean autoCommit)
throws SQLException
Sets this connection's auto-commit mode to the given state. If a connection is in auto-commit mode, then all its SQL statements will be executed and committed as individual transactions. Otherwise, its SQL statements are grouped into transactions that are terminated by a call to either the method commit or the method rollback. By default, new connections are in auto-commit mode.
The commit occurs when the statement completes. The time when the statement completes depends on the type of SQL Statement:
For DML statements, such as Insert, Update or Delete, and DDL statements, the statement is complete as soon as it has finished executing.
For Select statements, the statement is complete when the associated result set is closed.
For CallableStatement objects or for statements that return multiple results, the statement is complete when all of the associated result sets have been closed, and all update counts and output parameters have been retrieved.
NOTE: If this method is called during a transaction and the auto-commit mode is changed, the transaction is committed. If setAutoCommit is called and the auto-commit mode is not changed, the call is a no-op.
The above means, that your code, which is running in auto-commit mode, is equivalent to:
set transaction read write;
commit; -- invoked by JDBC autocommit
update user_tbl set name='mark' where email='m#xyz.com';
commit; -- invoked by JDBC autocommit
update user_tbl set name='ken' where email='k#xyz.com';
commit; -- invoked by JDBC autocommit
--if other things are successful, then:
commit;
commit; -- invoked by JDBC autocommit

When do I have to commit?

I heard in SQL I do not have to commit every statement. Perhaps create I don't have to.
So can you answer me which Statements I have to commit?
I read, that I have to commit all transactions, but I don't know what this is and can't find it anywhere.
Thanks for your help.
Per the SQL standard, most statements that require a transaction will automatically open one.
Some database engines, such as SQL Server, will (by default) automatically commit the transaction if the statement completes successfully. See Autocommit Transactions.
Autocommit mode is the default transaction management mode of the SQL Server Database Engine. Every Transact-SQL statement is committed or rolled back when it completes
SQL Server also has an Implicit Conversions mode which will leave the transaction open until it's explicitly commited.
When operating in this second such mode (which is the default, I believe, for Oracle), or if you've explicitly created a transaction, it's up to you as a developer when to commit the transaction. It should be when you've accomplished a "complete" set of operations against the database.
If you BEGIN a transaction then you have to either ROLLBACK or COMMIT
Example:
BEGIN TRAN
--Your code
INSERT INTO
NewTable
SELECT *
FROM TABLE
COMMIT TRAN
If you do not use that, it is committed upon execution. So the follow will either fail or be committed:
INSERT INTO
NewTable
SELECT *
FROM Table
If there is an error (like there is no NewTable in the DB) the execution will raise an error and the transaction will roll back. If there is no error the transaction will be committed.

Is there a difference between a SELECT statement inside a transaction and one that is outside of it?

Does the default READ COMMITTED isolation level somehow makes the SELECT statement act different inside of a transaction than one that is not in a transaction?
I am using MS SQL.
Yes, the one inside the transaction can see changes made by other previous Insert/Update/delete statements in that transaction; a Select statement outside the transaction cannot.
If all you are asking about is what the Isolation Level does, then understand that all Select statements (hey, all statements of any kind) - are in a transaction. The only difference between one that is explicitly in a transaction and one that is standing on its own is that the one that is standing alone starts its transaction immediately before it executes it, and commits or roll back immediately after it executes;
whereas the one that is explicitly in a transaction can (because it has a Begin Transaction statement) can have other statements (inserts/updates/deletes, whatever) occurring within that same transaction, either before or after that Select statement.
So whatever the isolation level is set to, both selects (inside or outside an explicit transaction) will nevertheless be in a transaction which is operating at that isolation level.
Addition:
The following is for SQL Server, but all databases MUST work in the same way. In SQL Server the Query Processor is always in one of 3 Transaction Modes, AutoCommit, Implicit, or Explicit.
AutoCommit is the default transaction management mode of the SQL Server Database Engine. .. Every Transact-SQL statement is committed or rolled back when it completes. ... If a statement completes successfully, it is committed; if it encounters any error, it is rolled back. This is the default, and is the answer to #Alex's question in the comments.
In Implicit Transaction mode, "... the SQL Server Database Engine automatically starts a new transaction after the current transaction is committed or rolled back. You do nothing to delineate the start of a transaction; you only commit or roll back each transaction. Implicit transaction mode generates a continuous chain of transactions. ..." Note that the italicized snippet is for each transaction, whether it be a single or multiple statement transaction.
The engine is placed in Explicit Transaction mode when you explicitly initiate a transaction with BEGIN TRANSACTION Statement. Then, every statement is executed within that transaction until you explicitly terminate the transaction (with COMMIT or ROLLBACK) or if a failure occurs that causes the engine to terminate and Rollback.
Yes, there is a bit of a difference. For MySQL, the database doesn't actually start with a snapshot until your first query. Therefore, it's not begin that matters, but the first statement within the transaction. If I do the following:
#Session 1
begin; select * from table;
#Session 2
delete * from table; #implicit autocommit
#Session 1
select * from table;
Then I'll get the same thing in session one both times (the information that was in the table before I deleted it). When I end session one's transaction (commit, begin, or rollback) and check again from that session, the table will show as empty.
The READ COMMITTED isolation level is about the records that have been written. It has nothing to do with whether or not this select statement is in a transaction (except for those things written during that same transaction).
If your database (or in mysql, the underlying storage engine of all tables used in your select statement) is transactional, then there simply no way to execute it "outside of a transaction".
Perhaps you meant "run it in autocommit mode", but that is not the same as "not transactional". In the latter case, it still runs in a transaction, it's just that the transaction ends immediately after your statement is finshed.
So, in both cases, during the run, a single select statement will be isolated at the READ COMMITTED level from the other transactions.
Now what this means for your READ COMMITTED transaction isolation level: perhaps surprisingly, not that much.
READ COMMITTED means that you may encounter non-repeatable reads: when running multiple select statements in the same transaction, it is possible that rows that you selected at a certain point in time are modified and comitted by another transaction. You will be able to see those changes when you re-execute the select statement later on in the same pending transaction. In autocommit mode, those 2 select statements would be executed in their own transaction. If another transaction would have modified and committed the rows you selected the first time, you would be able to see those changes just as well when you executed the statement the second time.