On Sat, 11 Apr 2015, Xiangrong Fang wrote:

Hi All,

Sorry that I don't know if SQLDB belongs to fpc or lazarus, so I posted to both 
lists.

I am confused about the use of transaction in SQLDB. I tried to use in in my 
non-gui app. Here is the code:

function TPortfolio.ConfirmTransaction(id: Integer): Boolean;
begin
  with qr do begin
    SQL.Text := Format('UPDATE records SET status=%d WHERE id=%d AND status=%d',
      [TR_SUCCESS, id, TR_PENDING]);
    ExecSQL;
    WriteLn('Confirming: ', id, ', affected: ', RowsAffected);
    //tr.Commit;
    //WriteLn('Confirming: ', id, ', affected: ', RowsAffected);
    Result := RowsAffected > 0;
  end;
end;
It seems that I must assign a TSQLTransaction object to the TSQLQuery object, 
otherwise it doesn't work. I also found that
without call tr.Commit, the ExecSQL will not take effect, at least for INSERT 
statements.  

In the above function, I found the first WriteLn will output rows-affected as 
1, and the 2nd (after tr.Commit) will output
rows-affected as -1!  I then commented out the tr.Commit; statement, it STILL 
worked.

Now my questions are:

1. How to control the use of transactions in SQLDB? Sometime I do NOT want 
transaction, but want the DDL/DML statement to be
executed immediately.  Why sometime SQLDB's ExecSQL won't take effect if not 
followed by a Commit? BTW, I tried to set tr.Active
to true/false before execute the sql, but it seems not making a difference?

All SQL engines use transactions. Every command is always executed in the 
context of a transaction.
Some of them just start and commit a transaction implicitly, around each command, if you don't do it explicitly yourself. Most people are perfectly happy with this, and for simple applications, this is probably enough.

SQLDB forces you to be aware of all this, by requiring you to start and commit 
each transaction explicitly.
However, most commands will start a transaction behind the scenes. They will not commit it, however, requiring you to commit it, since you would not be able to rollback if you wanted this.

[Note to self: add this to documentation]

Now, we realize that this is some extra work, so, in trunk, there are 2 options 
to control this behaviour:

- An option to TSQLTransaction, called stoUseImplicit, which means the implicit 
transaction handling of the engine will be used.
  (SQLDB then simply doesn't start a transaction)

  This has the effect that every statement will then be committed at once.

- An option to TSQLQuery called sqoAutoCommit, which will commit each statement 
at once.
  i.e. it calls SQLTranaction.Commit after each command.


2. What is the meaning of -1 as returned by RowsAffected?

Open will normally not return RowsAffected (so it returns -1). ExecSQL should return the actual number of affected rows.
If -1 is returned, then either the transaction was committed, or the SQL engine 
you use doesn't support it.

You must always examine RowsAffected before Committing. Commit resets all 
results and whatnot,
and normally also closes any datasets connected to the transaction.
This behaviour again can be avoided with some option, but this option has side 
effects.

Michael.
--
_______________________________________________
Lazarus mailing list
[email protected]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply via email to