ApplyUpdatesができない

解決


サンプー  2005-04-19 16:24:00  No: 14371

何時もお世話になります。
画面に、TQuery,UpdateSQL,Edit1,Edit2、Buttonを配置、Buttonを押すとアップデートを実行するように、以下のコードを記述しました。2点ほど、わからず、困っています。どなたかご教示ください。
Del6Pro,XpPro,BDEです。

UpDateSQL文は、以下の通りです。
update "User3.db"
set
  Memo03 = :Memo03
where
  Memo03 = :OLD_Memo03
**ここでひとつ疑問点、
  ’User3.db:項目名を決定できませんでした。’警告文:

以下記述したコード
procedure TFormSub.Button1Click(Sender: TObject);
 var S1,S2,S3 : String; 
 begin
 try
   DMSyaken.SyakenMainQuery.DisableControls;
   DMSyaken.SyakenMainQuery.Close;
 S1 := Edit1.Text;
 S2 := Edit2.Text;
   DMSyaken.SyakenMainQuery.Open;
   DMSyaken.SyakenMainQuery.First;
   while not DMSyaken.SyakenMainQuery.Eof do
 begin
   DMSyaken.SyakenMainQuery.Edit;
  if DMSyaken.SyakenMainQuery.FieldByName('Memo03').Text <> '' then
  begin
   S3 := DMSyaken.SyakenMainQuery.FieldbyName('Memo03').AsString;
   S4 := StringReplace(S3,S1,S2,[rfReplaceAll]);
   DMSyaken.SyakenMainQuery.FieldByName('Memo03').Text := S4;
    DMSyaken.SyakenMainQuery.Post;
    DMSyaken.SyakenMainQuery.Next;
   end
  else
   DMSyaken.SyakenMainQuery.Next;
 end;
    DMSyaken.SyakenMainQuery.ApplyUpdates;
  finally
      DMSyaken.SyakenMainQuery.EnableControls;
  end;

プログラムが暴走してしまう。


HOta  2005-04-19 16:55:13  No: 14372

TQueryのSQL・UpdateSQLの設定はどうなっていますか?
また、対象のDBは何でしょう?

[項目名を決定できませんでした。]
多分、複数のテーブルを扱っているのでしょうが、同じ項目名が
別のテーブルにあり、決定できないのでしょう。


サンプー  2005-04-19 18:17:09  No: 14373

HOTAさん、いつもレス有難うございます
//TQueryのSQL・UpdateSQLの設定はどうなっていますか?
//また、対象のDBは何でしょう?
TQueryのSQLは以下の通りです
select distinct * from user1.db,user2.db,user3.db
Where (User1.UserID = User2ID)
and   (User1.UserID = User3ID)
and   (User1.CarID = User3.CarID)
この中の、User3.dbにあるMemo03の項目を変換したいと思っています。
User3.DBのMemo03項目にあるDBEdit1.Text の文字列をEdit2.Textに変換する試みを行っています。

//[項目名を決定できませんでした。]
//多分、複数のテーブルを扱っているのでしょうが、同じ項目名が
//別のテーブルにあり、決定できないのでしょう。
この場合の対処法はどのようにすれば良いのでしょうか?項目名を変更したくないときはどのようにすれば良いのでしょうか?


HOta  2005-04-19 18:38:26  No: 14374

>select distinct * from user1.db,user2.db,user3.db
>Where (User1.UserID = User2ID)
>and   (User1.UserID = User3ID)
>and   (User1.CarID = User3.CarID)

この場合、SQL文の中でdistinctが使われていて、
どの行を対象に更新すればよいかわからなくなり、
[項目名を決定できませんでした。]の表示が出ます。
素直に、別にUpdateするためのTQueryを用意して、
そちらで変更しましょう。


サンプ  2005-04-20 08:10:18  No: 14375

TQuery のSQL文を
from ":syakenDB:User3.db" d, ":syakenDB:Car1.db" d1, ":syakenDB:Car2.db" d2, ":syakenDB:Car0.db" d3から

from User3.db as d,User0.db as d1へ変更すると
[項目名を決定できませんでした。]の表示はなくなり、プログラムは正常に動くようです。なんとかこれで解決しました。

//また、対象のDBは何でしょう?
paradox7です。DBに更新をかけるには、単にApplyUpdatesを使うだけでは、ダメなのでしょうか?


HOta  2005-04-20 15:24:56  No: 14376

何かDBが最初と違っていますね?
UpdateSQLはどのようになっていますか?
更新するレコードが特定できないと、
[項目名を決定できませんでした。]の表示が出ます。
ApplyUpdatesは、TUpdateSQLがCacheに
それまでにUpdateやInsert・deleteしたレコードを貯めておき、
それを元のDBに適用するComandです。


サンプー  2005-04-21 16:56:43  No: 14377

//何かDBが最初と違っていますね?
HOtaさん、アドバイス色々ありがとうございます。色々試行錯誤している中での質問ですので、はずしていることもあるかもしれません。何せ、初心者の初心者なので。

//UpdateSQLはどのようになっていますか?
UpdateSQL1のSQL文は、以下の通りです。
update "User3.db"
set
  Memo03 = :Memo03
where
  UserId = :OLD_UserId

//更新するレコードが特定できないと、
//[項目名を決定できませんでした。]の表示が出ます。
この問題は、解決できました。

色々、やって最終的には以下のコードに変更しましたが、今度は新しいエラーメッセージ
"テーブルの数が多すぎます.User.table3.db"が出てしまいます。何か、あり地獄に踏み込んだようで、めげそうです。解決策をご教示願います。

procedure TFormSub.Button1Click(Sender: TObject);
 var S1,S2,S3,S4,S5 : String; //user0,user3のテーブルのmemo03項目を同時に変換するため
 begin
 try
//画面のちらつきをなくす目的。
   DMSyaken.SyakenMainQuery1.DisableControls;
   DMSyaken.SyakenMainQuery1.Close;
 S1 := Edit1.Text;
 S2 := Edit2.Text;
   DMSyaken.SyakenMainQuery1.Open;
   DMSyaken.SyakenMainQuery1.First;
   while not DMSyaken.SyakenMainQuery1.Eof do
 begin
    DMSyaken.SyakenMainQuery1.Edit;
  if DMSyaken.SyakenMainQuery1.FieldByName('Memo03').Text <> '' then
   with DMSyaken.SyakenMainQuery1 do
   begin
   S3 := DMSyaken.SyakenMainQuery1.Fields[14].Text;
   S5 := DMSyaken.SyakenMainQuery1.Fields[50].Text;
   S4 := StringReplace(S3,S1,S2,[rfReplaceAll]);
   S3 := S4;
   S5 := S4;
    DMSyaken.SyakenMainQuery1.Post;
    DMSyaken.SyakenMainQuery1.Next;
   end
  else
   DMSyaken.SyakenMainQuery1.Next;
 end;

  finally
      DMSyaken.SyakenMainQuery1.EnableControls;
      ShowMessage('変換が終わりました');
     DMSyaken.DBSyaken.ApplyUpdates([DMSyaken.SyakenMainQuery1]);
  end;
 end;


HOta  2005-04-21 23:29:46  No: 14378

ちょっと問題を整理しましょう
まず、SyakenMainQuery1のSQL文は、
>select distinct * from user1.db,user2.db,user3.db
>Where (User1.UserID = User2ID)
>and   (User1.UserID = User3ID)
>and   (User1.CarID = User3.CarID)
ですね?
そのUpdateSQLのUpdateプロパティは
>update "User3.db"
>set
>  Memo03 = :Memo03
>where
>  Memo03 = :OLD_Memo03
ですから、"User3.db"のMemo03フィールドを更新するのですね。
でも、このソースからは、編集するフィールドが見あたりません。
これでは変更できていないはずです。

ソースを表示する前に、各テーブルがどうなっているかを
見せてもらえませんか?


サンプー  2005-04-22 00:15:18  No: 14379

HOTAさん、有難うございます。
解りました。今、会社にいるので、自宅に帰ってからメールします。


サンプー  2005-04-22 09:26:48  No: 14380

HOTAさん、親切にありがとうございます。
色々試す内に、大分変わってきて、以下のようになっています。
TQUERY のSQLは
 SELECT d.*, d1.*
 FROM User3.db as d, User0.db as  d1
WHERE
 (d1.UserId = d.UserId)

そのUpdateSQLのUpdateプロパティは以下の通りです。
update "User3.db" d
set
 d. Memo03 = :Memo03
where
  d.UserId = :OLD_UserId

user0.dbは、
userID Name1, Name2, Add1, Add2, Kata, Nen,・・,Memo03,・・・・・と項目が50個あります。  

user3.dbは、
userID Name1, Name2, Add1, Add2, Kata, Nen,・・,Memo03,・・・・と項目が16個あります。
上に示した項目名は、同じ項目名が数箇所あります。
やりたいことは、リストボックスに値を表示して、この値をMemo03項目の変更前の値とし、変更後の値をEdit2に書き入れ、ボタンをクリックするとUser0.db,User3.db双方のMemo03項目が変更されるようなプログラムを考えています。
よろしくご教示願います。


サンプー  2005-04-22 10:00:23  No: 14381

すみません。追加です。
User0.db,User3.dbいずれのデータも2000件位のデータで検証しています。
たまに、"テーブルが多すぎます。User3.DB"のエラーメッセージが出ます。
これは、データ数が多すぎるためでしょうか?もしそうであれば、どのような対処法があるのでしょうか?併せて、ご教示ください。


HOta  2005-04-22 16:40:58  No: 14382

同じ項目名が多いというこっとは、データーバースの設計ができていないことになります。どちらの項目が正しいか判らなくなります。もう一度設計し直しましょう。
データがたかだか2000件でおかしくなることはありません。これは、EDit〜Postがきちんとしていない影響が考えられます。

編集するコードが見あたりません。これでは変更できていないはずです。
一番簡単なのは、選択するTQueryと更新するTQueryを別にする方法もあります。
このまま使うなら、
> begin
>    DMSyaken.SyakenMainQuery1.Edit;
>  if DMSyaken.SyakenMainQuery1.FieldByName('Memo03').Text <> '' then
>   with DMSyaken.SyakenMainQuery1 do
>   begin
>   S3 := DMSyaken.SyakenMainQuery1.Fields[14].Text;
>   S5 := DMSyaken.SyakenMainQuery1.Fields[50].Text;
>   S4 := StringReplace(S3,S1,S2,[rfReplaceAll]);
>   S3 := S4;
>   S5 := S4;
>    DMSyaken.SyakenMainQuery1.Post;
>    DMSyaken.SyakenMainQuery1.Next;
>   end
>  else
>   DMSyaken.SyakenMainQuery1.Next;
> end;
でEditした後は、必ずPostかCancelをしましょう。そのままNextしてはいけません。また、編集したS4をS3,S5に返していますが、レコードには一切適用していません。これではレコードは変更していません。項目を番号で扱っていますが、名前で扱った方がソースの解読性がよくなります。

  with DMSyaken.SyakenMainQuery1 do
    while not Eof do
    begin
      if FieldByName('Memo03').asString <> '' then
      begin
        Edit;       //ここで編集状態にする。
        S3 := Fields[14].asString;
        S3 := Fields[50].asString;
        S4 := StringReplace(S3,S1,S2,[rfReplaceAll]);
        Fields[14].asString := S4;   //編集した文字列を項目に設定する
        Fields[50].asString := S4;
        Post;                        //ポストする
      end;
      Next;
    end;
//この後ApplyUpdatesする


サンプ  2005-04-22 19:00:06  No: 14383

HOTAさん早々のレス有難うございます。
今晩、早速試してみます。
色々ご丁寧なご教示、痛み入ります。
DELPHIを独学中の身、というか本格的なプログラミングは初めての経験で戸惑うというか意味不明のことばかりですが、今後もよろしくお願いします。


HOta  2005-04-23 01:34:39  No: 14384

DelphiはRAD Toolの中でデーターベースが一番簡単に使えます。
それも、TDataSetから派生したTTablやTQueryがあり、派生元であるTDataSetの使い方は、TTablやTQueryは同じように使えます。また、それぞれの使い方もできます。
TQueryで直接AppendやEditができますが、これ以外に、別のTQueryでInsert・Updateすることもできます。ものによれば、この方が処理が早いことがあります。ただ、プログラムはちょっと複雑になります。


サンプ  2005-04-23 07:44:28  No: 14385

HOtaさん、色々ありがとうございました。
最終的に、User0.dbとUser3.dbにそれぞれTQueryとUpDateSQLを準備し、それぞれのテーブルを別々に変換することによって期待どうりの結果を得ることが出来ました。長い間、懇切丁寧なアドバイス、誠にありがとうございました。

[同じ項目名が多いというこっとは、データーバースの設計ができていないことになります。どちらの項目が正しいか判らなくなります。もう一度設計し直しましょう。]
過去に業務用のソフトを購入しています。このソフトは、そのまま使おうかと考えています。今回は、このソフトのデータを下に、私なりに蓄積したデータを加工や、使いやすいように、あるいは新しい機能を付加したいと思い立って、自分でプログラムを考えていました。従って、テーブルの再設計が出来ないという制約がありました。あしからず、ご了承ください。


サンプー  2005-04-23 19:26:53  No: 14386

すみません
解決のチェックマークを忘れてました


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

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






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