On Wed, 18 Mar 2015 21:15:20 +0000
Simon Slavin <slavins at bigfraud.org> wrote:

> A transaction is ended when you issue the COMMIT command.  A
> transaction fails if any command which changes the database in it
> fails due to violating the schema.  If a transaction fails then all
> commands in it are automatically ignored.  There's no need to use
> ROLLBACK.  You correctly grouped commands together into a transaction
> and SQL knows that if any of them fail none of them must be executed.

$ sqlite3 :memory:<<EOF
create table T(t int primary key);
begin transaction;
insert into T values (1);
insert into T values (1);
commit;
select * from T;
EOF

Error: near line 4: UNIQUE constraint failed: T.t
t         
----------
1         

I'm not sure what you mean by "if a transaction fails". Transactions
don't succeed or fail as far as SQL is concerned; statements do.
Statements in the transaction that raise errors don't cause the
transaction to abort or roll back. All statements within the
transaction that succeed do leave the database in a changed state.  

The OP may be familiar with some other SQL.  Other flavors of SQL (most,
I'd say) support testing for @@error or somesuch in SQL, and branching
accordingly.  In SQLite, that's done by submitting each statement one
at a time, checking the error returned to sqlite3_exec, and deciding in
C whether or not to commit or rollback the transaction.  

It's a challenge to execute the above script from the command
line.  As written, it inserts one row.  With "or abort" it aborts, sure
enough, but still leaves one row.  With "or rollback" it inserts no
rows but produces "no transaction is active".  About the best result is
gotten by ignoring "or <anything>", writing standard SQL, and relying
on -bail to exit on error, whereupon SQLite reaches end-of-input
without an explicit COMMIT, and rolls back.  

--jkl

Reply via email to