DBGridに表示したデータをTableに登録/更新するには?

解決


平井  2003-12-02 07:23:52  No: 5845

初めて投稿します。宜しくお願いします。

複数のTableよりTQueryで取得したデータをDBGridに表示しています。
表示内容をボタンのクリックで、新たなTableに登録または更新をUpdatesqlを利用して実装したいと考えています。
皆様、ご指導宜しくお願いします。

[環境]:WindowsXP,Oracle8


これだと  2003-12-02 08:00:20  No: 5846

質問があまりにも漠然とし過ぎていますよ。
やってみて、エラーが出るとか、ここが分からないとか
そういう質問ならレスも来ますが。最初から人に考えて
もらおうとするのはちょっとどうかと...


平井  2003-12-02 18:20:25  No: 5847

これだとさん  早速のレス、ご指摘ありがとうございます。

現在、TQuery,TDataSource,TUpdateSQL,TDatabase,TButton,TDBGridをFormに載せています。
それぞれの連携を http://forum.nifty.com/fdelphi/samples/00886.html を参考に設定しています。
⇒ DB1.ApplyUpdates([Query1]); //それを適用してDBを実際に更新する
この部分でエラーとなっているようで、次のエラーメッセージが表示されます。
  >プロジェクトABC.exeがEDBEngineErrorクラスの例外を生成しました。
  >’この操作は行えません。’

エラーに対してどのように対応してよいのか分かりません。
ご指導宜しくお願いします。


晩日  2003-12-03 02:56:30  No: 5848

静的なQueryを更新処理(Refresh)するには
close,openをする必要がありますが。
try
  :  
    Query1.ApplyUpdates;
    DB1.Commit;
  :  
except
  :  
    DB1.Rollback;
  :
end;
エラー箇所はDB1.ApplyUpdates([Query1]); ではなく
インデックスではないでしょうか?


えび  2003-12-03 03:38:42  No: 5849

EDBEngineErrorのオブジェクトにはErrosプロパティがあります
ErrorsオブジェクトにはMessageプロパティがありますので、
その内容を画面に表示してエラーの内容を確認してください。
エラーの内容が分かれば原因がつかめると思います。


平井  2003-12-03 06:33:49  No: 5850

晩日さん、えびさんレスありがとうございます。

UpdateSQLの利用方法を勘違いしていたらしく、
ヘルプ等を確認して、現在なんとか動いています。
SQLを長々と書くはめになりましたが…

また色々とご指導いただくときは宜しくお願いします。

ありがとうございました。


平井  2003-12-03 06:34:19  No: 5851

忘れてました。>【解決】


えび  2003-12-03 08:41:42  No: 5852

UpdateSQLはSQL句を勝手に作ってくれると思うんですけど。
>UpdateSQLの利用方法を勘違いしていたらしく、
さらに勘違いしてるかも知れませんよ、基本的にDB関係の
コンポーネントはSQL句をカリカリとコーディングしなくていいように
する為の物なので。
デルファイに付属のデモプログラムにもUpdateSQLを使っているのが
ありますので、見たら参考になるかもしれません。


平井  2003-12-03 18:01:56  No: 5853

えびさん  度々のご指摘ありがとうございます。

UpdateSQLでSQL文を作成することは理解できました。
TQueryで取得した各Fieldの値を利用して更新するように考えています。Fields[2].TextやDBEdit3.Textの値をどのようにUpdateSQL内で定義するのか
わからずに、ソース内にSQL文を書く方法を取らざるを得ませんでした。

そもそもUpdateSQLで、Fields[2].TextやDBEdit3.Textの値を定義することは可能でしょうか?その方法をご存知でしたらご指導お願い致します。


晩日  2003-12-03 18:49:48  No: 5854

UpdateSQLでSQL文を作成できたということは
パラメーターができていると思います。
 :
 :{以下は挿入}
  UpdateSQL1.Query[ukInsert].ParamByName('id').AsString:=Edit1.Text;
  UpdateSQL1.Query[ukInsert].ParamByName('param').AsString:=Edit2.Text;
  UpdateSQL1.Query[ukInsert].ParamByName('name').AsString:=Edit3.Text;
  UpdateSQL1.ExecSQL(ukInsert);
 :
 :
更新のみであれば使う必要は無いと思いますが。
>そもそもUpdateSQLで、Fields[2].TextやDBEdit3.Textの値を定義することは
>可能でしょうか?
はそういった意味ですか?


えび  2003-12-03 19:06:09  No: 5855

まず、Queryで取得したレコードは複数のテーブルを結合しているとして、
その編集はどのような形式なのでしょうか?
グリッド上で直接編集したいのか、選択した行を個別のEditに転記してそこから
更新するのか、などの作り方によって色々変わってきます。
一番単純なケースで、1テーブルからのみのレコード取得の場合はDBEditや
DBGridで編集した値は、勝手にUpdateSQLにセットされます。

3つ目のレスに書いてあるリンク先が見れないのでプログラムの形式が分かりま
せんが、どういうテーブルを取得して、どう更新したいのかが分かればもっと
簡単に出来る方法があると思います。


平井  2003-12-03 20:19:14  No: 5856

晩日さん  ご指導ありがとうございます。

利用イメージとしては、そのような感じです。
例としてあげていただいたソースの挿入はどこにどのように
設定してあげればよいのでしょうか?

勉強不足で申し訳ありません。
宜しくお願いします。


平井  2003-12-03 20:31:12  No: 5857

えびさん  ご指導ありがとうございます。

編集の方法ですが、GridではReadOnlyで、
別のTabSheet上のEdit、Memoに転記してから
編集を行っています。

TableAAA
id(key)
name

TableBBB
id(key)
address

TableCCC
id(key)
tel

TableXYZ
id(key)
name
address
tel

AAAより id と name、BBBより address、CCCより telを取得して、グリッドに表示。
エディットに転記して編集。
ボタンクリックで、テーブルXYZのid,name,address,telを更新。

このような機能の実装を考えています。
UpdateSQLのプロパティ設定のみで可能なのでしょうか?


えび  2003-12-03 21:08:17  No: 5858

先ず確認なんですけど、

AAAとBBBとCCCのテーブルを結合した結果の複数のレコードが
グリッドに表示されている。

グリッドで選択したレコードに該当するXYZのレコードが
・あれば更新
・無ければ追加

と、いう感じですか?


平井  2003-12-03 21:14:55  No: 5859

はい。そういう動作が理想です。


えび  2003-12-03 21:46:02  No: 5860

更新するのが1テーブルだけなら、Tableコンポーネントを使って
UpdateSQLなしで行きましょう。そのほうが簡単です。
1レコード毎の更新ならTableコンポーネント使うオーバーヘッドは無視できます。

1.
Tableコンポーネントを配置して、IndexNameをIDに設定する。
DataSourceコンポーネントを配置しTableとリンクさせる。
Name,Address,Tel等を編集するDBEdit,DBMemoを配置し、
DataSourceとリンクし、各フィールドをリンクさせる。

2.
現状で各項目に転記しているタイミングで、
Table.Locateメソッドで検索し、
レコードが無ければAppend、レコードがあればEditメソッドを実行。

各編集コンポーネントへはレコードの値が勝手に入ります。

3.
入力項目のチェックは、編集コンポーネントのTextプロパティではなく、
TableコンポーネントのFieldByName('項目名').As・・・(Integer/String)
でチェック。
例えば
with Table.FieldByName('ADDRESS') do
begin
  if AsString = EmptyStr then
  begin
    MessageDlg('住所を入力してください。');
    FocusControl;  //該当する編集コンポーネントに勝手にフォーカスが行きます
    Exit;
  end;
end;

4.
チェックが終わったら、Table.Postで登録されます。
UpdateとInsertを使い分ける必要はありません。

大まかにはこういう流れで良いですか?


平井  2003-12-03 22:29:17  No: 5861

丁寧なご指導に感謝しています。
流れはこれで良いと思います。

気になる点と、質問があるのですが…
複数のレコードを修正したあと、ボタンクリックを行い
テーブルに登録する場合、全ての修正が反映されますか?

2の処理ですが、どの部分に記述すればよいのでしょうか?
ここまでご指導いただいているのに、力不足で申し訳ありません。


えび  2003-12-04 02:46:34  No: 5862

テーブルに登録してもグリッドには反映されません。
Queryでは問合せを実行した時点でのデータしか取得出来ません。
ただし、取り出したレコードが1つのテーブルのみ参照している場合は
BDEが登録した内容をバッファに反映するので見た目上は最新の状態に
なりますけど。

今回のケースのようにテーブルを結合してレコードを取得する場合に
変更した内容を反映させたい場合は、Queryを一旦閉じて再度開く必要が
あります。
>UpdateSQLの利用方法を勘違いしていたらしく、
>ヘルプ等を確認して、現在なんとか動いています。
ひょっとしてこの時点では上手く動いてましたか?

データが複数のテーブルに渡り、その変更を即座に反映させたい場合は
SQL句でテーブルを結合するのではなく、テーブル毎にQuery/Tableの
データセットを用意して、参照項目という形で1レコードのように見せかける
事は出来ます。
(ピンと来ないかとは思いますけど...)

2の処理のタイミングですか、どのような画面かが分からないのではっきりとは
いえませんが、QueryのAfterScrollかグリッドのOnClickのイベントで良いの
では無いでしょうか。

>複数のレコードを修正したあと、ボタンクリックを行い
>テーブルに登録する場合、
1レコード毎に登録するのを前提に考えてました。
データベースへの反映は数レコード一括が良いですか?そうなると
キャッシュアップデートを使う必要が出て、さらにややこしくなりますけど。

ちょっと話が複雑になって来ましたかね、ちょっと流れが変わりますが
各テーブルのレコード数はどの位でしょう?オラクルなので規模が
大きそうですけど。
レコード数が少なければ、パフォーマンスを無視して簡単に済ませる方向で
も考えられます。


平井  2003-12-04 03:37:55  No: 5863

えびさん  毎回の丁寧なご指導に感謝しています。

現状の報告としまして、TQuery,TDataSource,TUpdateSQLを
利用してデータの更新処理を実装できました。
ただ、TUpdateSQLを使っているうちに入るのかどうかは疑問です。

現在の壁といえば、データがない場合に追加処理を行わせる。
といったところです。
更新先のテーブルの状況を調べて、更新か追加かの分岐を
行わせれば良いのでしょうが、現在格闘中です。

以前参考にしたサイトを元に、作成したソースを掲載したいと思います。
改良の余地はかなりあると思いますが、とりあえず動きますので…

  with Query do begin
    if Modified then                       //データの変更があったなら
      begin
        UpdateSQL.ModifySQL.Clear();
        UpdateSQL.ModifySQL.Add('update … );
        Post;                              //書き込む
      end;
    if State in [dsInsert, dsEdit] then    //挿入モードでデータが未入力なら
      Cancel;                              //キャンセルする
    if UpdatesPending then                 //CachedUpdatesが適用されていないなら
      begin
        Database.ApplyUpdates([Query]);  //それを適用してDBを実際に更新する
      end;
  end;

以上です。SQL文は省略していますが、ここが結構な量です。。
この部分を簡単にするためのTUpdateSQLだと思うのですが、
うまく使えていません。これすら勘違いかもしれません。

長々とすみません。さらなる改良に頑張ります。


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

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






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