2012年06月13日

BDE Decision Cube ComponentsをDelphi2007で使用

Delphi ver7に存在した、BDEのDecision Cube Componentsが、Delphi2007のコンポーネントパレット上から消えている。

ただ、ソースは残してあるようである。そこから、パレットに復原する方法。

ソースは、($BDS)\source\Win32\xtab にある。

上記ホルダにあるプロジェクトファイルを使って再構築するば良いのでだが、エラーが出る。
参照パッケージの追加が必要なようで、”参照の追加”で、dclbde.dcp の追加が必要なようである。
追加後、再構築すればOK。

Delphi2007のソースも値によってオーバーフローするバグ(?)は直っていないようで、下記の修正が必要。

//  procedure SetMemoryCapacity(Value: Integer);
  procedure SetMemoryCapacity(Value: Int64);
//  function GetMemoryCapacity: Integer;    adachi
  function GetMemoryCapacity: Int64;
〜〜〜〜
var
//  AvailableMemory: Integer;       { Memory available to allocate }   adachi
  AvailableMemory: Int64;       { Memory available to allocate }
//  TotalAllocatedMemory: Integer;  { Total allaocted by the array classes }adachi 2
  TotalAllocatedMemory: Int64;  { Total allaocted by the array classes }

定義部分のみ掲載なので、関連するメソッドのコード修正は必要。
posted by しんくそふと at 11:55| Comment(0) | TrackBack(0) | 開発TIPS

2013年02月08日

ADOQuery 集計Query

ADOQueryで、集計Queryを使用するとき、LockTypeをltReadOnlyとする必要があるみたい。
デフォルトは、ltOptimisticとなっている。

デフォルトのままだと、
ORA-00937: not a single-group group function.
のエラーが出る。
posted by しんくそふと at 18:17| Comment(0) | TrackBack(0) | 開発TIPS

2013年05月30日

コンポーネントの切り替えでdfmファイルを直接書き換える

BDEからFireDACコンポーエントの書き換えなどを行う場合、dfmファイルを直接書き換えることで作業の短縮を図ることができる。
ただ、危険なので必ずバックアップを取ってから行うほうが良い。失敗すると開けなくなります。

一応、試しているのは、Delphi2007までです。これ以降のバージョンについても可能だとは思いますが、Unicodeで保存された場合は、どうなるかはまだ試していません。
まず、dfmファイルをテキスト形式で保存する必要がある。
テキスト形式かどうかは、フォーム上で、マウス右クリックで表示されるメニューで確認できる。
テキスト形式で保存された場合、テキストエディタで書き換え可能となるので、文字列変換機能などを使って、まとめて、クラスを変えてしまうことができます。
この時、pas側は変更しておく必要がありません。IDEで開いて、保存するときに、IDEが変換してくれます。
事前に、変更していくのもよいかもしれませんが、この方法だと変換されるコンポーネントが確認できます。
また、元のコンポーネントにあって、切り替え後のコンポーネントにない、プロパティやイベントは、削除されますがこれも、削除する旨の警告メッセージが出ます。

いきなり、実際に使っているプログラムを使うと、コンポーネントが多いので確認が難しいため、テスト用に、コンポーエントが少ない画面を作ってから行うほうが良いともいます。

dfmファイルを見ているとわかりますが、継承オブジェクトは、inherited。継承していないのは、objectで定義されています。
フォームも同様で、TFormから継承したFormを、TFormから直接継承するのではなく、間に継承Formを挟みたいときは、pasの書き換えとともに、dfmファイルの先頭行の、Formの定義の"object"を"inherited"に書き換えてあげれば可能です。
pasの TForm1 = class(TForm)の書き換えだけでは、ダメで、dfmの変更も必要です。
posted by しんくそふと at 22:26| Comment(0) | TrackBack(0) | 開発TIPS

BDE ⇒ FireDAC変換 (ソース変換)

dfm直接書き換えで、BDE=>FireDACに書き換えた時の記録です。

データベースはOracle。一時作業用にParadoxを使用。
すべてのプロジェクトで同じようにいくとは限りません。たまたま、弊社で対応したものの記録です。少しは参考になると思います。

一時作業用(Paradox)のTTableのTADMemTable化を先にやります。
TTable
 =>
  TADMemTable
この後一度、IDEで開いておいたほうが良いです。

次に、オラクルアクセス用のコンポーネントの変換
DMDataBase.OraDBは、TADConnectionの名前です。
----------------------
TTable
 =>
TADTable
    Connection = DMDataBase.OraDB

* SchemaNameを指定するとテーブルがないとエラーが出ることがある。この場合、 SchemaNameは削除する。
----------------------
TQuery
 =>
TADQuery
    Connection = DMDataBase.OraDB
----------------------
TUpdateSQL
 =>
TADUpdateSQL
    Connection = DMDataBase.OraDB
----------------------
各コンポーエントのDatabaseNameプロパティを削除しておいてもよいが、今回はそのまま残し、削除は、IDE任せで行った。
ADOコンポーネントの時のように、イベントが消えることもないのでそのあたりのフォローは少なくて済む。
TUpdateSQLも、TADUpdateSQLとして残るので助かる。
TADQueryの項目のDisplayLavelプロパティで、"#,#" はNG(メモリ例外)。
”0,#”にするとOKなところがあった。(原因は不明)

以下は、データマッピング機能を使うと変換の必要がないのかもしれないが、今回は使用せず、また次回試すことにする。

----------------------
TFloatField
 =>
    TBCDField
    Size = 0
ただし、小数項目は Size = 2 後で変更
----------------------
これはソース側。TADStoredProcのParamsの設定
AsInteger => value
AsDate => value
AsDateTime => value
----------------------
TADStoredProcで、IDE上で、StoreProcNameを再設定しないとパラメータ設定部分でエラーが出るものがいくつか発生(すべてでない)
StoreProcNameを一度クリアして、再設定してやるとうまく行くようになった。これも原因は今のところ不明。
TADQueryで、同様に、SQLを再設定してやらないと、上記と同様、パラメータ設定部分でエラーが出るものがいくつか発生(SoredProcより少ない)
これも、SQLを一度クリアして再設定で治った。こちらは、同一名のパラメータ名が複数あるときに起きるようだ。



FireDACへの変換も一通りのテストはやはり必要なようで、ノンテストで置き換えられるコンポーネントはないものか。。。。無理かな?...more
posted by しんくそふと at 23:04| Comment(0) | TrackBack(0) | 開発TIPS

2013年12月12日

Delphiマイグレーション記録 GKit

自社オリジナル開発での使用実績はなかったが、他社が開発したもののマイグレーション案件で数社使用されていることが確認された。
Borland Edtionというのが提供されていたようだ。製品サイトを見てい見ると、DelphiVer6あたりまでサポートされていたよう。
http://jp.fujitsu.com/group/fae/support/gkitocx/updatesp4b.html

今回、Delphi2007へのマイグレーションだったので、残念ながら、Bplファイルなどのサポートはない。

ベースはActiveXなので、ActiveXからタイプライブラリを作成、ラッパファイルをそれに対応して修正することで対応できた。

ただし、いくつかプロパティやメッソドの修正が必要となったり、実行時使えないものがあったので若干のソース修正が必要になった。
このあたりの確認は、生成された、タイプライブラリの確認が必要となる。


GKitの使用感は、高機能であるけど。。。費用(工数)の余裕があるなら、他のものに変えたほうが良いのかな。という感じ。
posted by しんくそふと at 09:29| Comment(0) | TrackBack(0) | 開発TIPS

Delphiマイグレーション記録 VBReport

自社オリジナル開発での使用実績はなかったが、他社が開発したもののマイグレーション案件で数社使用されていることが確認された。
VB-Report (ActiveX版)使用のプログラムを、Delphi2007へマイグレーションを実施。
サポートに連絡することにより、Delphi 2007用パッケージファイルをもらうことができた。

こちらは、メーカーが今でもサポートしてくれているよう。
http://www.adv.co.jp/support/product/support_vb-report2007.htm
特に旧版で問題は出てなかったようだが、最新の、Dllを取得する。


#(2017.1.11追記)
dllのバグ修正は、今も継続いるようです。
http://www.adv.co.jp/download/download-confrm.php?skey=54A&ftype=U
posted by しんくそふと at 09:51| Comment(0) | TrackBack(0) | 開発TIPS

2013年12月15日

dfmファイルを弄る

(Delphi Advent Calender2013投稿記事です)

BDEコンポーネントの切り替え方法として、
.dfmファイルを直接書き換える話をするのですが、.dfmファイルを直接弄るということをする人が少ないようなので、以前の記事に追加して少しまとめて見ます。テーブルコンポーネントの切り替え以外にどれだけ役に立つかは微妙なところですが、知っておくとまれに役立ちます。

.dfmファイルは、Delphi Ver5Ver6あたり(いまいちきちんと覚えていない)から、テキスト形式で保存できるようになっています。また、IDE上でテキスト表示もできます。


今回は、Delphi2007でいろいろ試しています。

メニューのツール=>オプション=>VCLデザイナで、テキスト形式で保存するかの指定ができます。
とりあえず、ボタンコンポーネントとパネルコンポーネントを張ったFromのソースを見てみます。

Objectの後に、オブジェクト名とクラス名がありその後にプロパティ(下記例では“〜〜略〜〜”の部分でこの例では省略します)が表示されます。プロパティは、デフォルト設定値以外のプロパティが表示されます。


Formも同じで、Formの中に各コンポーネントがあると構造も表現されています。


object Form1: TForm1

〜〜略〜〜

  object Button1: TButton

〜〜略〜〜
 
end

  object Panel1: TPanel

〜〜略〜〜
 
end

end


構造が表現されているという例で下記のように修正してみます

object Form1: TForm1
〜〜略〜〜

  object Panel1: TPanel

〜〜略〜〜
   
object Button1: TButton

〜〜略〜〜

  
  end

 
end

end


変更後、フォームとして表示すると、パネルコンポーネントの中に、ボタンコンポーネントが表示されるようになります。

このフォームを継承し、テキストがどのようになるか見てみます。

inherited Form2: TForm2

〜〜略〜〜

  inherited Panel1: TPanel

〜〜略〜〜
    inherited Button1: TButton

〜〜略〜〜

    end

 
end

end


object の部分がinheritedになっています。Formも同様です。


継承オブジェクトについては、このように定義が変わります。プロパティは、継承元と違うものが出力されます。

上記例では、ボタンコンポーネントとパネルコンポーネントの情報が表示されていますが、これは位置を少しずらしたため出力されていて、もし何も変えていない場合、これらは表示されません。
新たに、パネルにボタンを追加すると


inherited Form2: TForm2

〜〜略〜〜

  inherited Panel1: TPanel

〜〜略〜〜  
     inherited Button1: TButton
〜〜略〜〜
  

     end

     object Button2: TButton
〜〜略〜〜

     end
 
end

end


こんな感じで、objectが追加されることになります。


次に、コンポーネントクラスの切り替えを弄ります。

以前記事でも書きましたがDfmファイルのクラス定義を修正し、フォーム表示に切り替え後、保存すると、pasファイルとクラスの定義が違うけど、pasの定義を変更するかという確認メッセージが表示され、OKを押すと、pasファイルの定義を自動で変更してくれます。また、互換のないプロパティやイベントは無効となりますので注意が必要です(フォーム表示時に発生します。具体例は、後述)。
上記で、
Button2TBitBtnに変更します。その後、フォーム表示に変更します。見た目は変わらないのでこの状態ではわかりません。
保存します。

---------------------------

エラー
---------------------------
フィールド Form2.Button2 は TBitBtn 型であるべきですが,TButton として宣言されています。宣言を修正しますか?
---------------------------
はい(Y)   いいえ(N)   キャンセル   ヘルプ(H)  
---------------------------
というダイアログが出ます。“はい”を押した後に、
pasファイルを確認すると、

   Button2: TBitBtn;
という感じで書き換わっています。


ちょっと遊んでみます。

ここで、エディタに戻って、TBitBtn TEditに変えます。
---------------------------

フォームの読み込み中のエラー
---------------------------
Button2.Captionの読み込み中のエラー:プロパティCaptionは存在しません。エラーを無視して続行しますか?

注意:エラーを無視すると、コンポーネントまたはプロパティが失われる可能性があります。

---------------------------
無視(I)   キャンセル   すべて無視(A)  
---------------------------

“無視”を押すと、フォーム表示され、
BitBtnだったものが、Editコンポーネントに変わっています。



このように、互換のないプロパティやイベントについては無効になるので注意が必要で、重要なプログラムについて作業を行う場合、確認しながら進める必要があります。手抜きをして上記画面で“すべて無視”を選んでしまうと後で公開することもあるので面倒でも、確認しながら、“無視”ボタンをひとつづつ確認するのが無難です。


最後の例は、あまり意味ないですが、この、dfmを直接書き換える方法は、BDEコンポーネントの切り替えなどには、役立つと思います。


まだ弄ったことがない人は一度、いろいろ試してみてください。


<注意>

最後に、慣れないうちはバックアップを取ってから修正するようにしてください。修正時、コンポーネント構造がおかしくなると、フォーム表示に復活できなくなります。


posted by しんくそふと at 17:16| Comment(0) | TrackBack(0) | 開発TIPS

2014年02月05日

Delphiマイグレーション記録 QuickReport


QuickReport

Pro版(Ver5)を購入で、最新バージョンをダウンロード可能。
残念ながら、VCL版のみだが、64bit版もある。

一度購入すれば、Delphi新バージョンに対応したものが、ダウンロード可能。
〜Xe7版もダウンロードできる(2014/10/3確認)
Xe8版も確認(2015/6/18)
10Seattle版も確認(2016/5/9,たぶんもっと以前に公開されていたと思う)
10Berlin版も確認(2016/5/9)

#
Delphi2007についてくるバンドル版は、Ver4なので注意が必要。
一部イベント引数の方が変わるので注意。
Sender:TQuickRep が、 Sender:TCustomQuickRep
定義を変えるだけで対応できる。とりあえず上記の変更が必要。今のところこの修正だけで弊社が対応したシステムでは済んでいる。

...more
posted by しんくそふと at 10:41| Comment(0) | TrackBack(0) | 開発TIPS

2014年04月03日

FireBird gbak Restoreパラメータ


gbak -r -p 8192 -v -user sysdba -pas ????? -FIX_FSS_METADATA SJIS_0208 -FIX_FSS_DATA SJIS_0208 -REP (backup file) (DB)

上書きパターン

-FIX_FSS_METADATA SJIS_0208
-FIX_FSS_DATA SJIS_0208

Ver2.*から上記のように文字コードの指定を付けないとうまく行かないケースがある。
posted by しんくそふと at 16:24| Comment(0) | TrackBack(0) | 開発TIPS

2014年06月12日

Delphi開発での印刷処理実装


弊社で使用している印刷モジュールの紹介です。
いろいろなところで印刷をどうしているか、どうするかという話によくなりますので、弊社が使用しているものの紹介をします。。

http://www.hos.co.jp/package/cr10/
弊社では、伝票などの単票形式の印刷にはこれを使っています。

残念ながら、Delphiのコンポーネントとしては、提供されていないですが、ActiveXですので、定義を取り込んでDelphiコンポーネントを作成し、使用しています。

特にこのプログラムの機能で気に入っているというか、この機能を使いたいがために弊社で使用しています。
弊社では、次の2点の特徴で、採用を決めました。
1.レイアウト関係の情報が、定義ファイルとして、別ファイルにできること
2.日本の会社が開発しているので、マニュアル等が日本語。問い合わせも日本語でできる(外国語が苦手です)

2はよいとして、1についてもう少し詳しく。
a)
ちょっとしたレイアウトの修正は、プログラムを修正することなく、この定義ファイルの差し替えで対応できます。
b)
扱うデータは、同じだけど、レイアウトが異なる帳票で、プログラムはそのままで使用する定義ファイルの切り替えのみで対応できます。
弊社では、印刷時のダイアログで、定義ファイルを選択できるようにして、印刷時にユーザーが選択できるようなクラスを作成しています。
これは、たとえば、郵便物の宛名書きなどがよい例だと思いますが、使用する封筒サイズごとの定義ファイルを作成。
印刷時に選択することによりそろぞれのレイアウトで印刷できます。
これにより、封筒サイズごとにプログラムを書く必要がなく、定義ファイルの変更で済ませることができます。
荷物の配送で複数の業者を使っている場合など、送り状が異なりますが、これも配送業者ごとにプログラムを書く必要がなく、定義ファイルの切り替えで対応しています。
これの応用で、明細行の異なる帳票も定義ファイルに非表示の明細行数を埋め込むことにより、上記のように定義ファイルの切り替えで対応できます。
また、明細項目の増減も、定義ファイルの工夫で同様に対応できます。

バーコードなども対応していますので、帳票作成をどうするかで迷われているのであれば、一同検討の価値はあると思います。
体験版もあります。
ただ、ネックは、ちょっと高いことです。以前は、もう少し安いエディションがあったのですが、いつの間にかなくなってしまった。。。

---------------------------------------------------------------------------

弊社でも、このソフトを取り扱っていますのでお問い合わせください。
 問い合わせ先メールアドレス mailto:eigyo2.bu@thinksoft.co.jp

---------------------------------------------------------------------------...more
posted by しんくそふと at 19:15| Comment(0) | TrackBack(0) | 開発TIPS

2014年07月25日

FastReportおぼえ 1


直接コードで、オブジェクトに値を設定する方法

frxReport.(FindObject('XXXXXX') as TfrxMemoView).Text := 'XXXXXXX';
FasReport雑感
DBとの連携レポートは作りやすそうだが、上記の様に直接オブジェクトに値を入れたりするのはちょっと作りにくい。
特に、オブジェクト名の確認のため、いちいちレポート定義を開いて閉じて(定義を開いたままDelphiコードを編集できない)を繰り返さないといけないのが面倒。製品版購入でこのあたりを解消できるのだろうか?



posted by しんくそふと at 13:05| Comment(0) | TrackBack(0) | 開発TIPS

FastReportおぼえ 2


ラインの追加
var
  Line : TfrxLineView;

begin
〜〜〜〜
    with frxReport  do
    begin
      Line  := TfrxLineView.Create(FindObject('Sheet') as TfrxReportPage);
                                                                      //↑追加するシート名
      Line.Left := ******;
      Line.Top := ******;
      Line.Width := ******;
      Line.Height := *******;
      Line.ShowHint := False;
      Line.Diagonal := True;
    end;


posted by しんくそふと at 13:10| Comment(0) | TrackBack(0) | 開発TIPS

Excel出力コンポーネント XE6対応


以前公開したExcel出力コンポーネントですが、DelphiXE6でもパッケージを作成しなおせば、使用可能と思います。
サンプルプログラムを少し改修中で、近々、公開予定です。
(まだ、時々ダウンロードしていただけているようなので、ご案内)



...more
posted by しんくそふと at 15:29| Comment(0) | TrackBack(0) | 開発TIPS

2014年08月01日

FastReport:プレビュー画面で印刷 or PDFエクスポートした後もプレビューを続ける方法


プレビュー画面から印刷 or PDFエクスポートする

*印刷
このときプリンタなどの設定は、frxReport1で行う。
    frxReport1.PrintOptions.ShowDialog := False;
    frxReport1.PrintOptions.Printer := ’ぷりんた名’;
    frxPreview1.Print;

*PDFエクスポート
    frxPDFExport1.FileName := "ファイル名.pdf"
  frxPreview1.Export(frxPDFExport1);

frxPreview1は、プレビューで使っているコンポーネント。


(2014.9.30 未完成状態で公開したようで、修正)

タグ:FastReport
posted by しんくそふと at 19:14| Comment(0) | TrackBack(0) | 開発TIPS

2014年10月16日

TClientDataSetとTFDMemTable


画面での編集用や、印刷時の、一時テーブルに、TClietnDataSetを使っていた。
FireDACには、同様の用途として、TFDMemTable があり、FireDACに置き換えたプロジェクトには、こちらを使っている。
で、パフォーマンスは違うのかどうなのだろうと気になり確認しました。


DelphiXE7で、テストプログラムは作成しています。
フィールドは、TLargeintFieldを1項目と、TIntegerFieldを10項目で作成しています。
TClietnDataSetについては、LogChanges=Falseに設定している。

Win32 データ100万件 (仮想マシン上で実行。メモリ3G割当設定)
 TFDMemTableTClientDataSet
Append
 7.300 Sec
6.630 Sec
 5.117 Sec
5.148 Sec
Close
 0.171 Sec
0.188 Sec
2.356 Sec
1.575 Sec

Win64 データ1000万件
 TFDMemTableTClientDataSet
Append
 54.618 Sec
54.825 Sec
 45.277 Sec
45.126 Sec
Close
1.555 Sec
1.655 Sec
 92.922 Sec
92.635 Sec

それぞれ2度づつ計測している。
Append処理は、若干、TClietnDataSetのほうが早いようだ。
ちょっと気になるというのかわからないのは、Closeで、TClietnDataSetが時間がかかる件。
タスクマネージャで見ていると、TFDMemTablは、Closeで一気にメモリ使用量が減るが、 TClietnDataSetは、Close後もしばらく増加傾向が続きその後、減少しているようだ。
TFDMemTableはs、Win32で、1000万件も処理できたが、TClietnDataSetでは、追加は動いたが、Close時に
---------------------------
Insufficient memory for this operation.
---------------------------
のエラーが出てしまう。(なので、上記テストは、Win32は、100万件としている)

全件追加した状態のタスクマネージャの観察してみると、TClietnDataSetのほうが、メモリの使用量が少ないようだ。メモリ管理を効率化してしまったがために、CLose時、何か問題を引き起こすようなことになっているのだろうか。Win64では、とりあえず、今回のテストでは同様の問題は起きない。

TFDMemTableのAppend、Closeのメモリの動き(わかりやすい)
増加のところは、Appendです。Appendが終わると増加はとまる。
Closeで一気に使用分が減る。


TClientDataSet 赤マーク部分でAppend終了、すぐにClose
なぜかCloseしても、使用メモリは増える。
緑でClose終了。黄色は、プログラム終了。
Closeでメモリ量が元に戻らないので、注意が必要ということか。。。。。


...more
posted by しんくそふと at 17:59| Comment(0) | TrackBack(0) | 開発TIPS

2014年11月08日

FastReport の使用



FastReport は、製品版の購入がお勧め。
なんといっても日本語のマニュアル&ヘルプがついている。
バンドル版よりバージョンもひとつ上だし。

* 最近、ブログの検索ワードで、FastReport が増えてるので、ちょっと書いてみました

追記

ただし、FireMonkey版は、扱いなしとのこと。。。

posted by しんくそふと at 09:43| Comment(0) | TrackBack(0) | 開発TIPS

2014年12月07日

意外と使われていない便利なプロパティ Forms.Constraints編

Delphi / Appmethod Advent Calendar 2014 投稿記事です

弊社、いろいろな会社がDelphiで作成したプロラムのメンテを多くさせていただいています。
その中で、あまり使われていないor知られていないけど、便利なプロパティについて紹介します。
(えらそうに書いているけど、他者が作ったプログラムをメンテさせていただいている中で気づいたというのが真相ではあります。。。。)


今回(次回があるかは不明)は、Forms.Constraintsです。


これは、Formをリサイズできるようにした場合の、変更できる高さや幅の制限をかけることができるプロパティです。下記の4点の指定ができます。
MaxHeight
MaxWidth
MinHeight
MinWidth

かつて(ずいぶん前)は、画面の解像度は限られたもので、事前に、画面設計も解像度などを決めて作成していました。


最近は、解像度も多種になり、特に一覧表示などは自由に表示サイズを変えたいという要望がでます。

設定は簡単に変えられるのですが、ボタンが見えなくなるなどで、ある程度のサイズより小さくならないように設定しておく必要が出ます。
このような場合、MinHeight、MinWidthにサイズ指定を指定しておくことで対応ができます。



posted by しんくそふと at 11:38| Comment(0) | TrackBack(0) | 開発TIPS

CoReportのDelphiでの利用



2014・11・11 東京ライトニングトークで話した資料です。
以前、"Delphi開発での印刷処理実装"の中で紹介した印刷コンポーネントでもあります。

段取り悪く、話しきれなかったことはおいおい、記事にしていきたいと思います。


資料中にある、サンプルの販売は、ライトニングトークでのデモのものに、もう1〜2点追加予定です。
ただいま準備中ですので、固まりましたら、詳細をHP等でご案内させていただきます。



posted by しんくそふと at 12:00| Comment(0) | TrackBack(0) | 開発TIPS

2015年12月17日

DB登録方法の違いによるパフォマンス比較

この投稿はDelphi Advent Calendar 2015の21日目の記事です。


同じコンポーネントを使っても、データベースに登録する方法は複数あります。
今回は、その方法の違いによるパフォーマンスの比較をしたいと思います。

コンポーネントは、FireDACを使います。Delphiは、10 Seattle、データベースは、PostgreSQLを使いました。
データは、日本郵便株式会社のサイトからダウンロードした郵便番号データを使用しました。
件数は、123907件です。項目は、新旧郵便番号と、県市区町村名のカナと漢字名で9項目のフィールド対象としています。
このデータをテーブルに追加する処理で確認します。

登録方法の比較は下記の3種類。すべて、TFDQueryを使います。

1)
ChashUpdateを使用し、全件Append->Post後、ApplyUpdatesする。

2)
Insert文を使い、ExecSQLで1件づつ全件登録します。

3)
同じく、Insert文を使用し、配列DMLを使います。
配列数は2パターン計測したものを示します。


計測値です。それぞれ2回行っています。

パターン1回目(hh:nn:ss.zzz)2回目(hh:nn:ss.zzz)
1) 00:04:23.610 00:06:49.251
2) 00:01:22.688 00:02:21.500
3)  ArraySize = 5000 00:00:07.126 00:00:07.031
3)  ArraySize = 10 00:00:28.047 00:00:41.969

配列DMLでArraSizeが大きいものが圧倒的に早いようです。
データ移行や、バッチ系の処理で、処理時間が気になるようなときは、配列DMLが有効なようです。

ArraySizeは、大きいほうがよいと言うこと上記からわかりますが、あまり大きくするとメモリのエラーが出ます。
最初、ArraySizeをデータ件数(123,907)にしたら駄目でした。1万件でも駄目で、上記5000件はOKでした。
その間は確認してません。
このあたりはパラメータの項目数などによって、調整が必要なようです。
ここのQ4に情報があるようです。いまいち意味がわからないですが、結局環境によって違うってことなのかな。

posted by しんくそふと at 16:26| Comment(0) | TrackBack(0) | 開発TIPS

2016年05月18日

結合クエリのCashUpdate更新(サンプルソース付)

結合クエリのCashUpdate方法ポイント

Delphi 10 Seattle
DBアクセス:FireDAC、DatabaseはSQLiteで確認しています。
他のコンポーエントやデータベースでも考え方は同じなので適用できると思います。

----------------------------------------------------------------------------------------------

テーブル(伝票の明細を編集するイメージです)
 伝票明細(Meisai)、商品マスタ(Syouhin) (1:N関連)

CREATE TABLE "MEISAI" (
    `ORDERNO`    INTEGER NOT NULL,
    `MEISAINO`    INTEGER NOT NULL,
    `SYOUHINCODE`    INTEGER NOT NULL,
    `TANKA`    REAL DEFAULT 0,
    `SURYO`    REAL DEFAULT 0,
    `BIKOU`    TEXT DEFAULT '',
    PRIMARY KEY(ORDERNO,MEISAINO)
)
CREATE TABLE "SYOUHIN" (
    `SYOUHINCODE`    INTEGER NOT NULL,
    `SYOUHINNAME`    TEXT,
    `SYOUHINTANKA`    REAL,
    PRIMARY KEY(SYOUHINCODE)
)

----------------------------------------------------------------------------------------------

クエリ
select
 M.ORDERNO
,M.MEISAINO
,M.SYOUHINCODE 
,S.SYOUHINNAME
,S.SYOUHINTANKA
,M.TANKA        /*<=更新対象*/
,M.SURYO        /*<=更新対象*/
,M.BIKOU        /*<=更新対象*/
from
  MEISAI M        /*<=更新するテーブルはこの位置で無いといけない*/
  inner join SYOUHIN S
  on (S.SYOUHINCODE = M.SYOUHINCODE)
where
 M.ORDERNO = :ORDERNO
order by
 M.MEISAINO

----------------------------------------------------------------------------------------------

FDQuery
 上記クエリを設定後、フィールドエディタでフィールドの展開をする必要がある。

FDQueryのdfmファイル内容(関係ない部分は一部削除しています)
  object QryList: TFDQuery
    OnCalcFields = QryListCalcFields
    CachedUpdates = True
    SQL.Strings = (
      'select'
      ' M.ORDERNO'
      ',M.MEISAINO'
      ',M.SYOUHINCODE'
      ',S.SYOUHINNAME'
      ',S.SYOUHINTANKA'
      ',M.TANKA'
      ',M.SURYO'
      ',M.BIKOU'
      'from'
      '  MEISAI M'
      '  inner join SYOUHIN S'
      '  on (S.SYOUHINCODE = M.SYOUHINCODE)'
      'where'
      ' M.ORDERNO = :ORDERNO'
      'order by'
      ' M.MEISAINO')
    object QryListORDERNO: TIntegerField
      FieldName = 'ORDERNO'
      ProviderFlags = [pfInWhere, pfInKey]
    end
    object QryListMEISAINO: TIntegerField
      FieldName = 'MEISAINO'
      ProviderFlags = [pfInWhere, pfInKey]
    end
    object QryListSYOUHINCODE: TIntegerField
      FieldName = 'SYOUHINCODE'
      ProviderFlags = [pfInUpdate]
    end
    object QryListSYOUHINNAME: TWideStringField
      FieldName = 'SYOUHINNAME'
      ProviderFlags = [pfHidden]
      ReadOnly = True
    end
    object QryListSYOUHINTANKA: TFloatField
      FieldName = 'SYOUHINTANKA'
      ProviderFlags = [pfHidden]
      ReadOnly = True
    end
    object QryListTANKA: TFloatField
      FieldName = 'TANKA'
      ProviderFlags = [pfInUpdate]
    end
    object QryListSURYO: TFloatField
      FieldName = 'SURYO'
      ProviderFlags = [pfInUpdate]
    end
    object QryListCalKINGAKU: TIntegerField
      FieldKind = fkCalculated
      FieldName = 'CalKINGAKU'
      Calculated = True
    end
    object QryListBIKOU: TWideStringField
      FieldName = 'BIKOU'
      ProviderFlags = [pfInUpdate]
    end
  end
------------------------------------
ポイントは、ProviderFlagsになります。
更新するフィールドは、pfInUpdateをTrueにする。
更新時の、Where句に相当する部分は、pfInWhereをTrueにする。
join先のテーブルのフィールドは、pfHiddenをTrueにする。
テーブルの主キーのフィールドは、pfInKeyをTrueにする(ふつう勝手にTrueになる)

結合クエリとは関係ないが、BDE=>FireDAC切り替え時、BDEでは設定しなくても
問題なかった、キー項目のProviderFlagsが、未設定だとエラーが出る。
エラー(例外:EFDDBEngineException)が出たらキー項目の下記の確認を。
ProviderFlags = [pfInWhere, pfInKey]
エラー内容は何パターンかあるようだ。
 メッセージ [FireDAC][Phys][IB]-312.〜〜〜〜
 メッセージ [FireDAC][DApt]-400.〜〜〜〜
など。


上記だけではわかりにくいかと思うのでサンプル(ソースのみ)を下記にアップ。データベースも含めています。


(含 LookUpフィールドサンプル。)
明細の追加や削除は考慮して作っていません。上記確認のためなので諸々端折っています。

追記。。。。

今回のケースでは、
--------------------------------
from
  MEISAI M        /*<=更新するテーブルはこの位置で無いといけない*/
  inner join SYOUHIN S
  on (S.SYOUHINCODE = M.SYOUHINCODE)
--------------------------------
の部分は、下記のようなLeft Outer Joinでも使えます
(仕様としては、商品マスタが無い商品を取り扱うというのは、NGですが)
--------------------------------
from
  MEISAI M        /*<=更新するテーブルはこの位置で無いといけない*/
  left outer join SYOUHIN S
  on (S.SYOUHINCODE = M.SYOUHINCODE)
--------------------------------
でもOK。
right outer join や full outer join は、当然ダメ。
ちなみにもともと、SQLiteは、right outer join / full outer join をサポートしていませんが。
他のデータベースをつかうときの注意点です。

ついでに。
たぶんやろうとしないと思うけど、まとめて複数のテーブル(今回では、MEISAIとSYOUHIN)を更新もNGです。


追記その2。。。。
(結合クエリとLookupフィールドについて。私論)

上記の処理では、SYOUHINCODEも変更するということが一般だと思う。
この場合、上記結合テーブルで行うと、SYOUHINCODEが変わったときの処理、コードでゴリゴリ書く必要が出てくる。
そのように考えると、SYOUHINテーブルの引用は、Lookupフィールドを使ったほうが便利だと思う。

ただ、読み込むMEISAIテーブルのデータが少ないケースはそれでよいが、件数が多いケースでは、Lookupフィールドの使用は、格段に処理時間がかかる。そういったケースではコードでゴリゴリ書くことに目をつぶって、結合テーブルを使用することもメリットが出ると思う。


タグ:Delphi FireDAC BDE
posted by しんくそふと at 13:32| Comment(0) | TrackBack(0) | 開発TIPS