1トランザクションでの更新数制限を変更するには?

解決


せいにゃ  2003-10-16 05:55:09  No: 5210

1回のトランザクションで複数回データベースの更新を行う箇所があり、どうしても256件以上の更新を行う可能性があります。
Paraoxを使用しているのですが、255レコードまでは変更できるということはヘルプから判明しましたが、256レコード以上になるとやはりできませんでした。
これをできるようにする方法は何かあるのでしょうか。

Delphi7(Pro)+Paradoxでの環境です。


通りすがり  2003-10-16 17:59:21  No: 5211

うるおぼえモードですが。。。
トランザクション前にLockTable
トランザクション後にUnLockTable
だったような気が(??)


せいにゃ  2003-10-16 18:15:23  No: 5212

通りすがりさん、早速のアドバイスありがとうございます。
ご指摘の LockTable、UnLocktable を使用してみたのですが
やはり256件目でエラーとなってしまうようです。
以下にその部分の抜粋を置きますので、なんかおかしいところが
あれば、ご指摘ください。

例)単純なUPDATE文 'UPDATE TEST Set Item = :PItem WHERE Key = :PKey ;' を256回繰り返す部分の抜粋
    procedure AThread.AProc ;
    var
        cnt: Integer;
    begin
        Table1.Open;
        Table1.LockTable(ltWriteLock);
        Database1.TransIsolation := tiDirtyRead;
        Database1.StartTransaction;
        try
            for cnt := 0 to 256 do
            begin
                // ↓Query1(TQuery)にはSQLをセットしておきパラメータ 
                //  を変更して使用しています。
                Query1.close;
                Query1.ParamByName('PItem').AsString := 'Item';
                Query1.ParamByName('PKey').AsInteger := cnt;

                // ↓256件目でエラー
                Query1.ExecSQL;
            end;
            Database1.Commit;
            Table1.UnLockTable(ltWriteLock);
            Table1.Close;
        except


えび  2003-10-16 19:16:29  No: 5213

マニュアルを見ると
「最大ロック数の制限を越えるにはキャッシュアップデートしろ」
とありますね。


通りすがり  2003-10-16 20:05:23  No: 5214

Queryですか?
てっきり、以下のようなことを想定していました。
procedure AThread.AProc ;
var
  cnt: Integer;
begin
  Table1.Open;
  Table1.LockTable(ltWriteLock);
  Database1.TransIsolation := tiDirtyRead;
  Database1.StartTransaction;
  try
    {
    for cnt := 0 to 256 do
    begin
      // ↓Query1(TQuery)にはSQLをセットしておきパラメータ 
      //  を変更して使用しています。
      Query1.close;
      Query1.ParamByName('PItem').AsString := 'Item';
      Query1.ParamByName('PKey').AsInteger := cnt;
      // ↓256件目でエラー
      Query1.ExecSQL;
    end;
    }
    for cnt:=0 to 999 do
    begin
      Table1.EditKey;
      Table1.FieldByName('Key').AsInteger := cnt;
      if Table1.GotoKey then
      begin
        Table1.Edit;
        Table1.FieldByName('Item').AsString := 'Item';
        Table1.Post;
      end;
    end;
    Database1.Commit;
    Table1.UnLockTable(ltWriteLock);
    Table1.Close;
  except
    Database1.Rollback;
    Table1.UnLockTable(ltWriteLock);
    Table1.Close;
  end;
end;


masayan  2003-10-16 21:33:27  No: 5215

私もDelphi7 + Paradoxで開発していますがキャッシュアップデートを使っています。

    procedure AThread.AProc ;
    var
        cnt: Integer;
    begin
        Table1.Open;
        Table1.LockTable(ltWriteLock);
        
        // キャッシュアップデート開始
        Query1.CachedUpdates := True;
        for cnt := 0 to 256 do
        begin
          Query1.close;
          Query1.ParamByName('PItem').AsString := 'Item';
          Query1.ParamByName('PKey').AsInteger := cnt;

          Query1.ExecSQL;
          // 書き込んだ内容はキャッシュされ実際のテーブルには保存されない。
        end;

        Database1.StartTransaction;
        try
          Query1.ApplyUpdates; // キャッシュした内容を書き込み
          Database1.Commit;
        except
          Database1.Rollback; 
          raise;
        end;
        Query1.CommitUpdates; // キャッシュを空にする

        Query1.CachedUpdates := False;
        Table1.Close;
    end;

てな感じかな。
詳しくは、ヘルプでApplyUpdatesなどを検索してみてください。
※.机上コーディングなので間違えがあったらごめんなさい。


せいにゃ  2003-10-16 21:40:51  No: 5216

回答をいただいた皆様、アドバイスありがとうございます。

Queryだと、処理的に難しいんでしょうか?
処理速度が要求されてしまうので、Query を使用しています。
Table ごとの処理だと Query 使用時よりたくさん時間がかかるといわれたので・・・

皆様からのご指摘事項は実際の開発要員へ確認させています。(私自身は営業的な
立場なので・・・)

いろいろ試してみたいので、皆様、どうぞよろしくお願いいたします。


通りすがり  2003-10-17 17:28:27  No: 5217

本題とはずれてしまいますが、素朴な疑問を1つ。
>処理速度が要求されてしまうので、Query を使用しています。
>Table ごとの処理だと Query 使用時よりたくさん時間がかかるといわれたので・・・
とありますが、
例からすると257回もQueryを投げていますよね。
ループ処理になってしまう部分をQueryを使用することで、
1回なり少ない回数を投げてデータベース側に処理をお任せするんだと思うのですが。
単なる例ならば、どうでもいいんですけど。
失礼しました。


せいにゃ  2003-10-18 06:03:36  No: 5218

masayanさんからご指摘いただいたキャッシュアップデートの方法を試してみたところ、ApplyUpdates の個所でエラーが発生してしまいました。
"データセットが編集または挿入モードではありません"というエラーとなってしまうのです。
恐らくは ApplyUpdates を発行する前に何らかのモード切替処理が必要になるのだろう、と思っているのですが、よくわかりません。

ご存知の方、教えてください!


masayan  2003-10-18 19:19:10  No: 5219

せいにゃさん、ごめんなさい。
TQueryのExecSQL(SQLのUPDATE)によるレコード更新はキャッシュアップデートが効かないようです。
キャッシュアップデートは、データセットに対する更新や追加データをキャッシュしますが、ExecSQLでは、UPDATEやINSERTなどだけが実行されるとは限らないためだと思われます。(自分も昔、同じことでやった記憶が...)

できるのであればQuery1をTTableに変更できませんか?
例えば、変更処理を以下のようしてください。

  for cnt := 0 to 256 do
  begin
    if Table2.Locate(....) then // 変更対象の検索
    begin
      Table2.Edit;
      Table2.ParamByName('PItem').AsString := 'Item';
      Table2.ParamByName('PKey').AsInteger := cnt;

      Table2.Post;
    end;
  end;


せいにゃ  2003-10-23 05:33:13  No: 5220

皆様、お世話になっております。
いろいろ有意なご意見をありがとうございました。

1トランザクション中での更新件数を削減する方向で
修正をはじめました。ご指摘いただいた TTable につきましては
開発サイドでのノウハウ及び経験を考慮し、別手段にて回避するように
したようです。
時間はかかるかもしれませんが、なんとか解決の糸口が見えてきたような
感じです。

今まで、参考になるご意見をいただきました、
通りすがりさん、えびさん、masayanさん、本当にありがとうございました。

今後もよろしくお願いいたします。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加