Le 11/04/2015 16:29, Xiangrong Fang a écrit :
2015-04-11 15:41 GMT+08:00 SPRL AFOR <[email protected] <mailto:[email protected]>>:

    Michael's comments do not need further explanation

    If you want an Sql statement be executed immediately attach an
    TSqlTransaction to a DB component, attach the TSqlQuery  to the
    transaction and enclose it between a StartTransaction and a Commit.

    TR.StartTransaction;
    qr.ExecSql;
    TR.Commit;

    The Commit matters as well


​ As a matter of fact, I think yours and Michael's reply both answered part of my questions but not all. I am now clear about the meaning of RowsAffected returning value -1, but I am still not clear about WHY *sometime* I need to use Commit, but other times it is *not* necessary?

If the rule with SQLDB is that I always need to use Commit, fine, I am perfectly fine with this rule. But, in my function, th Commit is not necessary, even without it, the UPDATE takes effect. That's why I am confused: when must I use Commit, and when it is optional? Please note that:
As Michael wrote, a transaction is ALWAYS nedded. Full stop. Whether you manage it using components (like SqlDB) or the DBMS does the job the result is the same. Scheme is ALWAYS: StartTransaction, apply any Sql statements, Commit (or Rollback). If you do not explicitely do it, the DBMS will do it for you.

1) I am using SQLDB without a form, so all properties are at their default value, unless I explicitly change them -- I don't know there are options like
sqoAutoCommit
​ , and I didn't set any properties for sqldb components.​
DBMS options (set in params field in TSqlDB or TSqlTransaction). Check with Sqlite 3 database and transaction params

2) I am using SQLite3, on Ubuntu 14.10 64bit.​
Sqlite 3 is transaction compliant. Check ACID transaction params.

3) I even thought that Commit is necessary when using INSERT, but is optional if you use UPDATE, but that logic seems weird...​
Commit is not an option: it MUST be executed somewhere if you want your data be fixed in the database after the last (either explicit or implicit StartTransaction like in CommitRetaining). For all other transactions outside yours, data could not be in the last stable state (i.e. non visible) without a Commit. Depending on DBMS behaviour Sql statement will be auto-committed (MS SQL server) or you should do the job explicitely. DBMS ACID properties should help you to see what happens.

Just to see what happens, in your function, enclose all the with block between a TR.StartTransaction and a TR.Commit, like this:
  if not TR.InTransaction then
    TR.StartTransaction;
  with qr do begin
SQL.Text := Format('UPDATE records SET status=%d WHERE id=%d AND status=%d', [TR_SUCCESS, id, TR_PENDING]);
    ExecSQL;
    Result := RowsAffected > 0;
    WriteLn('Confirming: ', id, ', affected: ', RowsAffected);
  end;
  TR.Commit;


If you could explain why the behaviors are different that will be very helpful.

(read here <https://www.sqlite.org/lang_transaction.html> and here <https://www.sqlite.org/isolation.html>. This one maybe too here <https://www.sqlite.org/transactional.html>) For instance, using Firebird, Transaction params should be set to Concurrecy, NoWait to use the SNAPSHOT transaction isolation.

Antonio.
​ Thank you very much!​



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



---
L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel 
antivirus Avast.
http://www.avast.com
--
_______________________________________________
Lazarus mailing list
[email protected]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply via email to