IBDataSetについて教えてください。

解決


印刷屋  2007-12-29 22:41:16  No: 29122  IP: 192.*.*.*

FireBirdのテーブルがなんとか用意できました。

IBDatasetとIBDataBase、IBTransactionの組み合わせが一番シンプルだとようやく分かり、互いをリンクして、SELECT文を組み込んだんですが、その後のコーディングに悩んでいます。

InsertSQLに入力をせずに

  IBDataSet.Open;
  IBDataSet.Insert;
  IBDataSet.FieldByName('CODE').AsString := '000000';
  IBDataSet.Post;
  IBDataSet.Close;

でいこうとすると「書き込み禁止のデータは変更できません。」となり

InsertSQLに
INSERT INTO テーブル名 (CODE) VALUES(:CODE)

を入れた状態で

  IBDataSet.Insert;
  IBDataSet.ParamByName('CODE').AsString := '000000';
  IBDataSet.Post;

だと項目'CODE'がみつかりませんとなります。
標準的な扱いが分かるコードをおしえてもらえないでしょうか。
よろしくお願いします。

ちなみにDBControlを使わないコーディングにこだわってます。

編集 削除
DEKO  2007-12-30 06:20:42  No: 29123  IP: 192.*.*.*

単純にTIBQueryを使ってみてはどうでしょう?

IBQuery1.SQL.Text := 'INSERT INTO テーブル名 (CODE) VALUES(:CODE)';
IBQuery1.ParamByName('CODE').AsString := '000000';
IBQuery1.ExecSQL;

こんな感じです。
# ParamCheckプロパティはTrueにしておいて下さい。

編集 削除
印刷屋  2007-12-30 08:27:05  No: 29124  IP: 192.*.*.*

IBQueryって読み出し専用じゃないんですか?
IBQuery + IBUpdateSQL = IBDataSetだと思ってたんですけど…。

それから
データセットの編集でできるデフォルトSQLを入れて、
FieldByNameでのエラーは回避できました。

ただ、腑に落ちないのは
INSERT INTO テーブル名 (CODE) VALUES(:CODE)

IBDataSet.FieldByName('CODE').AsString := '000000';
すると
Values(:CODE)には何が入ってるんだろ?ってことです。

編集 削除
印刷屋  2008-01-01 21:38:02  No: 29125  IP: 192.*.*.*

なんとなく分かってきました。あくまでなんとなくですが…。

INSERT INTO ***
(CODE)
VALUE(:CODE)

とした場合、
サーバー側のフィールド名がCODE
キャッシュ内のフィールド名が:CODE
そこにFieldByName('CODE').AsStringで書き込んだ場合、
キャッシュ内の:CODEに書き込まれるんですね。

アホなんで気づくのに時間がかかりました。
DEKOさん方式もうまくいきました。

ちなみにこんな方法とどっちがいいんでしょうか?
  IBDataBase.Connected := True;
  IBTransaction.StartTransaction;
  try
    IBDataSet.Open;
    IBDataSet.Insert;
    IBDataSet.FieldByName('CODE').AsString := '123456';
    IBDataSet.Post;
    //コミット
    IBTransaction.Commit;
    IBDataSet.Close;
  except
    //ロールバック
    IBTransaction.Rollback;
    raise;
  end;
定石がわかんないんで、できればスマートなコーディングを覚えておきたいんで、よろしくお願いします。

編集 削除
明けおめ  2008-01-01 22:19:18  No: 29126  IP: 192.*.*.*

裕子:「ねぇ、お正月になって なんで今ごろ皆で餅つきなのぉ?」
春子:「しょうがないでしょ、超忙しかったンだから…、今日は、年末に手伝ってくれたお礼よ」
裕子:「そう言われて期待して来てみたら、また手伝いなんだからぁ〜…」
春子:「後でオモチたくさん食べられるから、…じゃ、マコトを呼んでくるね、おーい、マコト〜」
真琴:「…、は〜い」
春子:「何してたの?マコト」
真琴:「クリップボードのデータを一つのファイルに保存出来ないかなぁって、いろいろ試してた」
春子:「ん?それで、出来たの?」
真琴:「イチオウ…、なんとか」
春子:「そう? じゃ、後で見せてね、これから外で餅つき始めるから」
真琴:「うん、アタシ、つきたてのアンコ餅大好き、スグ行く」

const
  CLIPBOARD_FILE = 'ClipBrdFile.dat';

procedure TForm1.ButtonSaveClick(Sender: TObject);
 //---------------------------------------------------
 procedure Save_Clipboard(fmt: UINT; Writer: TWriter);
 var
  FmtStr: array[0..255] of Char;
  Data: THandle;
  DataPointer: Pointer;
 begin
  if GetClipboardFormatName(fmt, FmtStr, SizeOf(FmtStr)) = 0 then FmtStr[0] := #0;
  Data := Clipboard.GetAsHandle(fmt);
  if Data <> 0 then begin
   DataPointer := GlobalLock(Data);
   if DataPointer <> nil then begin
    try
     Writer.WriteInteger(fmt);
     Writer.WriteString(FmtStr);
     Writer.WriteInteger(GlobalSize(Data));
     Writer.Write(DataPointer^, GlobalSize(Data));
    finally
     GlobalUnlock(Data);
    end;
   end;
  end;
 end;
 //---------------------------------------------------
var
  fs: TFileStream;
  Writer: TWriter;
  i: Integer;
begin
  fs := TFileStream.Create(CLIPBOARD_FILE, fmCreate);
  try
   Writer := TWriter.Create(fs, $800);
   try
    Clipboard.Open;
    try
     Writer.WriteListBegin;
     for i:=0 to Pred(Clipboard.FormatCount) do
      Save_Clipboard(Clipboard.Formats[i], Writer);
      Writer.WriteListEnd;
     finally
      Clipboard.Close;
     end;
   finally
    Writer.Free
   end;
  finally
   fs.Free;
  end;
end;


procedure TForm1.ButtonLoadClick(Sender: TObject);
 //---------------------------------------------------
 procedure Load_Clipboard(Reader: TReader);
 var
  fmt: UINT;
  FmtStr: string;
  Size: Integer;
  Data: THandle;
  DataPointer: Pointer;
 begin
  fmt    := Reader.ReadInteger;
  FmtStr := Reader.ReadString;
  Size   := Reader.ReadInteger;
  Data := GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT or GMEM_DDESHARE, Size);
  if Data <> 0 then begin
   DataPointer := GlobalLock(Data);
   if DataPointer <> nil then begin
    try
     Reader.Read(DataPointer^, Size);
    finally
     GlobalUnlock(Data);
    end;
    if Length(FmtStr) > 0 then fmt := RegisterCLipboardFormat(PChar(FmtStr));
    if fmt <> 0 then begin
     Clipboard.Open;
     try
      Clipboard.SetAsHandle(fmt, Data);
     finally
      Clipboard.Close;
     end;
    end;
   end else begin
    GlobalFree(Data);
    OutOfMemoryError;
   end;
  end else
   OutOfMemoryError;
 end;
 //---------------------------------------------------
var
  fs: TFileStream;
  Reader: TReader;
begin
  fs := TFileStream.Create(CLIPBOARD_FILE, fmOpenRead or fmShareDenyNone);
  try
   Reader := TReader.Create(fs, $800);
   try
    Clipboard.Open;
    try
     Clipboard.Clear;
     Reader.ReadListBegin;
     while not Reader.EndOfList do Load_Clipboard(Reader);
     Reader.ReadListEnd;
    finally
     Clipboard.Close;
    end;
   finally
    Reader.Free
   end;
  finally
   fs.Free;
  end;
end;

真琴:「あれ?…ちょっと、ユウコ、ナニそれ…一人でアンコ食べちゃって…」
春子:「あぁ〜…、コラぁ〜…」
裕子:「だってぇ…、だって、だって、だってぇ…」
春子:「お餅ができる前にみんな食べちゃうつもり? ダメよ、こっちかして」
裕子:「イヤぁ〜…、もっと食べたいぃ」
真琴:「もう、ユウコったら…、ン?…あの音…まさか…」
春子:「え?、あれは…」
裕子:「あ…、あのクルマ…中にあの二人…」

広海:「よっ、マコト、久しぶり、…ほら、忘れ物」
春子:「あっ、それ、ヒロミくんが買ってくれたペンダントね」
真琴:「うん…、でも、なんでココにいるの? あの南の島で自分の海見つけたンじゃ…」
広海:「あそこはオレらの海じゃない…、ま、イロイロあって、強制送還、国外退去処分ってこと」
真琴:「えっ、強制送還? …なんで?ナニしたの?」
広海:「コイツが、可哀想なイルカ 海に逃がしてやりたいって言うんで」
春子:「逃がしちゃいけない大事なイルカを無断で? それを二人で? それで…」
海都:「さっき成田に着いて…、冬の海でも見て、これからのコト考えるかって…、ついでに新年のアイサツ」
広海:「明けまして、おめ…」
裕子:「あ…、クルマが…」
広海:「えっ?」
海都:「あっ、ブレーキ…」
広海:「おいっ、早く飛び乗ってクルマ止めろ〜」
海都:「あーっ、バカバカ、冬の海だけには落ちたくない〜…」
春子:「…あ〜ぁ落ちちゃった…、また同じパターン、いつもコレだよ」
真琴:「バ〜〜ッカみたい」
裕子:「マコト、なんかギガント嬉しそ」

編集 削除
お正月だし  2008-01-01 22:23:52  No: 29127  IP: 192.*.*.*

これ↑スレッド間違いだよね。
ま、いいか、お正月だし、おめでたいし...

編集 削除
通行人  2008-01-02 11:51:46  No: 29128  IP: 192.*.*.*

> 明けおめさん

..確かに、スレ違い?

でも、このシリーズ面白いので良く読ませてもらってます。
今年もユニークな回答待ってます、頑張って下さい。

編集 削除
DEKO  2008-01-04 15:41:18  No: 29129  IP: 192.*.*.*

>ちなみにこんな方法とどっちがいいんでしょうか?
テーブルがそこまで複雑でなければTIBDataSetを使うのがいいと思います。
前/次レコードへ移動できますから、カード型のUIを作るのが簡単ですし。
# カード型のUIの場合、どうしてもDBへの接続時間が長くなりがちなので、
# C/S型へのUIには向かないかもしれません。
# もちろん、スタンドアロンなら話は別です。

混み入ったテーブル構造の場合にはTIBQuery等を使って、
SQL文をコードで記述するのがメンテナンスが比較的楽になります(あくまで主観ですが)。
# 混み入ったテーブル構造になるのはそもそもDB設計が間違っているからですが、
# 建て増し構造だとどうしても複雑になりがちです。

どちらにせよ、いずれか片方で統一できるのであれば、
なるべく統一しておいた方が可読性は向上すると思います。

編集 削除
印刷屋  2008-01-04 20:21:54  No: 29130  IP: 192.*.*.*

いろいろ教えて頂いてありがとうございました。
なんとかIBXを使えそうです。

ところでカード型って言うのは1レコード毎の編集ってことですよね?
UIって何ですか?

編集 削除
DEKO  2008-01-04 23:51:47  No: 29131  IP: 192.*.*.*

> UIって何ですか?
何でも端折ればいいわけじゃないですね、スミマセン。
"User Interface"...操作する画面の事です。

先の"カード型"というのは、
[前へ ← カレント → 次へ]
というような操作ができる画面の事です。

編集 削除
take  2008-01-05 18:01:33  No: 29132  IP: 192.*.*.*

カード型C/Sを普通のコントロールでするのって難しいですね。(>_<)
BDEみたいにOpen→Closeでトランザクションを実現すると競合問題が出てくるし、開きっぱなしにしてると、どこで開始したトランザクションか分からないし。
Open=StartTransaction
Close=Commit
Cancel=Rollback
て訳じゃないんですよね?

編集 削除
印刷屋  2008-01-05 18:03:09  No: 29133  IP: 192.*.*.*

↑すいません。遊び用のハンドルが入ってしまいました。

編集 削除