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を使わないコーディングにこだわってます。
単純にTIBQueryを使ってみてはどうでしょう?
IBQuery1.SQL.Text := 'INSERT INTO テーブル名 (CODE) VALUES(:CODE)';
IBQuery1.ParamByName('CODE').AsString := '000000';
IBQuery1.ExecSQL;
こんな感じです。
# ParamCheckプロパティはTrueにしておいて下さい。
IBQueryって読み出し専用じゃないんですか?
IBQuery + IBUpdateSQL = IBDataSetだと思ってたんですけど…。
それから
データセットの編集でできるデフォルトSQLを入れて、
FieldByNameでのエラーは回避できました。
ただ、腑に落ちないのは
INSERT INTO テーブル名 (CODE) VALUES(:CODE)
で
IBDataSet.FieldByName('CODE').AsString := '000000';
すると
Values(:CODE)には何が入ってるんだろ?ってことです。
なんとなく分かってきました。あくまでなんとなくですが…。
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;
定石がわかんないんで、できればスマートなコーディングを覚えておきたいんで、よろしくお願いします。
裕子:「ねぇ、お正月になって なんで今ごろ皆で餅つきなのぉ?」
春子:「しょうがないでしょ、超忙しかったンだから…、今日は、年末に手伝ってくれたお礼よ」
裕子:「そう言われて期待して来てみたら、また手伝いなんだからぁ〜…」
春子:「後でオモチたくさん食べられるから、…じゃ、マコトを呼んでくるね、おーい、マコト〜」
真琴:「…、は〜い」
春子:「何してたの?マコト」
真琴:「クリップボードのデータを一つのファイルに保存出来ないかなぁって、いろいろ試してた」
春子:「ん?それで、出来たの?」
真琴:「イチオウ…、なんとか」
春子:「そう? じゃ、後で見せてね、これから外で餅つき始めるから」
真琴:「うん、アタシ、つきたてのアンコ餅大好き、スグ行く」
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;
真琴:「あれ?…ちょっと、ユウコ、ナニそれ…一人でアンコ食べちゃって…」
春子:「あぁ〜…、コラぁ〜…」
裕子:「だってぇ…、だって、だって、だってぇ…」
春子:「お餅ができる前にみんな食べちゃうつもり? ダメよ、こっちかして」
裕子:「イヤぁ〜…、もっと食べたいぃ」
真琴:「もう、ユウコったら…、ン?…あの音…まさか…」
春子:「え?、あれは…」
裕子:「あ…、あのクルマ…中にあの二人…」
広海:「よっ、マコト、久しぶり、…ほら、忘れ物」
春子:「あっ、それ、ヒロミくんが買ってくれたペンダントね」
真琴:「うん…、でも、なんでココにいるの? あの南の島で自分の海見つけたンじゃ…」
広海:「あそこはオレらの海じゃない…、ま、イロイロあって、強制送還、国外退去処分ってこと」
真琴:「えっ、強制送還? …なんで?ナニしたの?」
広海:「コイツが、可哀想なイルカ 海に逃がしてやりたいって言うんで」
春子:「逃がしちゃいけない大事なイルカを無断で? それを二人で? それで…」
海都:「さっき成田に着いて…、冬の海でも見て、これからのコト考えるかって…、ついでに新年のアイサツ」
広海:「明けまして、おめ…」
裕子:「あ…、クルマが…」
広海:「えっ?」
海都:「あっ、ブレーキ…」
広海:「おいっ、早く飛び乗ってクルマ止めろ〜」
海都:「あーっ、バカバカ、冬の海だけには落ちたくない〜…」
春子:「…あ〜ぁ落ちちゃった…、また同じパターン、いつもコレだよ」
真琴:「バ〜〜ッカみたい」
裕子:「マコト、なんかギガント嬉しそ」
これ↑スレッド間違いだよね。
ま、いいか、お正月だし、おめでたいし...
> 明けおめさん
..確かに、スレ違い?
でも、このシリーズ面白いので良く読ませてもらってます。
今年もユニークな回答待ってます、頑張って下さい。
>ちなみにこんな方法とどっちがいいんでしょうか?
テーブルがそこまで複雑でなければTIBDataSetを使うのがいいと思います。
前/次レコードへ移動できますから、カード型のUIを作るのが簡単ですし。
# カード型のUIの場合、どうしてもDBへの接続時間が長くなりがちなので、
# C/S型へのUIには向かないかもしれません。
# もちろん、スタンドアロンなら話は別です。
混み入ったテーブル構造の場合にはTIBQuery等を使って、
SQL文をコードで記述するのがメンテナンスが比較的楽になります(あくまで主観ですが)。
# 混み入ったテーブル構造になるのはそもそもDB設計が間違っているからですが、
# 建て増し構造だとどうしても複雑になりがちです。
どちらにせよ、いずれか片方で統一できるのであれば、
なるべく統一しておいた方が可読性は向上すると思います。
いろいろ教えて頂いてありがとうございました。
なんとかIBXを使えそうです。
ところでカード型って言うのは1レコード毎の編集ってことですよね?
UIって何ですか?
> UIって何ですか?
何でも端折ればいいわけじゃないですね、スミマセン。
"User Interface"...操作する画面の事です。
先の"カード型"というのは、
[前へ ← カレント → 次へ]
というような操作ができる画面の事です。
カード型C/Sを普通のコントロールでするのって難しいですね。(>_<)
BDEみたいにOpen→Closeでトランザクションを実現すると競合問題が出てくるし、開きっぱなしにしてると、どこで開始したトランザクションか分からないし。
Open=StartTransaction
Close=Commit
Cancel=Rollback
て訳じゃないんですよね?
↑すいません。遊び用のハンドルが入ってしまいました。
編集 削除