ネタキリラボ
ネタキリラボ[ラボ]

Delphiで組み込みFirebirdサンプル

準備

組み込みのFirebird Embedded ServerをDelphiから利用して簡単な住所・郵便番号検索データベースを作成したいと思います。

Firebird Embedded Server組み込み方法

※サンプルではすでに組み込まれています。

  1. Firebird日本ユーザー会ダウンロードページからリンクをとんでFirebird-xxxxxxxx_embed.zipをダウンロードして解凍してください。(私は2.0.4を使用しました。)
  2. 解凍したら、fbembed.dllのファイル名をgds32.dllに変更します。
  3. 解凍フォルダ内の以下のファイルをアプリケーションフォルダに配置します。
    アプリケーション.exe
    gds32.dll ← fbembed.dllのファイル名を変更したもの
    ib_util.dll
    icudt30.dll
    icuin30.dll
    icuuc30.dll
    firebird.conf
    firebird.msg
    intl/
      fbintl.dll
      fbintl.conf
    udf/
      fbudf.dll
    詳しくはFirebird日本ユーザー会にReadmeを日本語訳したREADME_embedded_JP.txtがあります。

Firebird Embedded Serverポイント


サンプルソース

作成フォーム

作成フォーム

実行フォーム

入力欄に住所の一部を入力すると、DB内から文字列が含まれている住所をインクリメンタルサーチします。

実行フォーム

ソース

データベースはアプリフォルダ内のPOST.FDBに接続しています。DBファイルはGUI管理ツールなどで作成し、POST_TABLEテーブルを作成しPOST_CODE,ADDRESSフィールドを追加しています。

レコードをINSERTする方法は3種類表記しました。速度も見れるようにしたのでコメントアウトしたり外したりして他の方法もお試し下さい。(※作者未熟のため他にもっと速いINSERT方法があるかもしれません。よろしかったら掲示板等で教えて頂けるとうれしいです。)

クエリはTIBTableのFilterを使用した方が簡単なので、Filterを使ってクエリしています。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IBDatabase, DB, IBCustomDataSet, IBTable, StdCtrls, Grids,
  DBGrids, ExtCtrls, Menus, DBCtrls, IBQuery, ComCtrls;

type
  TForm1 = class(TForm)
    IBTable1: TIBTable;
    IBDatabase1: TIBDatabase;
    IBTransaction1: TIBTransaction;
    DataSource1: TDataSource;
    Panel1: TPanel;
    DBGrid1: TDBGrid;
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    Open1: TMenuItem;
    Exit1: TMenuItem;
    N1: TMenuItem;
    OpenDialog1: TOpenDialog;
    IBTable1POST_CODE: TIBStringField;
    IBTable1ADDRESS: TIBStringField;
    Splitter1: TSplitter;
    LabeledEdit1: TLabeledEdit;
    DBNavigator1: TDBNavigator;
    Memo1: TMemo;
    IBQuery1: TIBQuery;
    ProgressBar1: TProgressBar;
    N2: TMenuItem;
    Label1: TLabel;
    procedure Exit1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Open1Click(Sender: TObject);
    procedure N2Click(Sender: TObject);
    procedure LabeledEdit1Change(Sender: TObject);
  private
    { Private 宣言 }
    procedure ClearTable;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//テーブルの全レコードを削除
procedure TForm1.ClearTable;
begin
  IBQuery1.SQL.Text := 'DELETE FROM POST_TABLE';
  IBQuery1.ExecSQL;
end;

procedure TForm1.Exit1Click(Sender: TObject);
begin
  Close;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  IBTable1.Open;
end;

//郵便番号データのインポート
procedure TForm1.Open1Click(Sender: TObject);
var DataList, RecList: TStringList; i, Count: Integer; 
  postcode, address: string; StartTime: Cardinal;
begin
  OpenDialog1.InitialDir := ExtractFileDir(Application.ExeName);
  if OpenDialog1.Execute then begin
    DataList := TStringList.Create;  //郵便番号データリスト
    RecList := TStringList.Create;   //郵便番号レコードリスト
    DBGrid1.Columns.BeginUpdate;
    DBNavigator1.Hide;
    try
      try
        ClearTable;
        DataList.LoadFromFile(OpenDialog1.FileName);
        Count := DataList.Count;
        ProgressBar1.Max := Count;
        StartTime := GetTickCount;  //INSERT前開始タイムを取得
        for i := 0 to Count-1 do begin
          RecList.CommaText := DataList[i];
          with IBTable1 do begin
            //郵便番号(7桁)
            postcode := RecList[2];
            //都道府県名 + 市区町村名 + 町域名
            address := RecList[6] + RecList[7] + RecList[8];  
            //INSERT方法3種、作者の環境では速さは 1<2<3 です。
            {INSERT方法1}
//            Insert;
//            FieldByName('POST_CODE').AsString := postcode;
//            FieldByName('ADDRESS').AsString := address;
//            Post;

            {INSERT方法2}
//            InsertRecord([postcode, address]);

            {INSERT方法3}
            with IBQuery1 do begin
              SQL.Text := 'INSERT INTO POST_TABLE VALUES (''' +
                postcode + ''', ''' + address + '''); ';
              ExecSQL;
            end;

            ProgressBar1.StepIt;
          end;
        end;
        IBTransaction1.Commit;
        Memo1.Lines.Add('');
        Memo1.Lines.Add(ExtractFileName(OpenDialog1.FileName) + 'のインポート');
        Memo1.Lines.Add('INSERT数 = ' + IntToStr(Count));
        Memo1.Lines.Add('総INSERT時間 = ' +
          IntToStr(GetTickCount - StartTime) + 'ms');  
        Memo1.Lines.Add('');
      except
        IBTransaction1.Rollback;
      end;
    finally
      IBTable1.Close;
      IBTable1.Open;
      DBNavigator1.Show;
      DBGrid1.Columns.EndUpdate;
      ProgressBar1.Position := 0;
      DataList.Free;
      RecList.Free;
    end;
  end;
end;

procedure TForm1.N2Click(Sender: TObject);
begin
  ClearTable;
  IBTransaction1.Commit;
  IBTable1.Close;
  IBTable1.Open;
end;

//住所のクエリ
procedure TForm1.LabeledEdit1Change(Sender: TObject);
var StartTime: Cardinal;
begin            
  StartTime := GetTickCount;
  with IBTable1 do begin
    Filter := 'ADDRESS LIKE ''%' + LabeledEdit1.Text + '%''';
    Close; Open;
  end;   
  Memo1.Lines.Add('クエリ時間 = ' +
          IntToStr(GetTickCount - StartTime) + 'ms');
end;

end.

速度

上のソースを元に以下の環境でインサートとクエリ速度を測ってみました。

実行環境

CPU:           Intel Core 2 Duo E6600 (Conroe-4M, B2)
               2400 MHz (9.00x266.7) @ 2383 MHz (9.00x264.8)
Memory:        2048 MBytes @ 331 MHz
Graphics:      Intel 82945G Integrated Graphics Controller [AsusTek]
               Intel GMA950, 128 MB 
OS:            Microsoft Windows XP Professional Build 2600

同じ動作を3回ずつ計測します。

INSERT処理

東京都の全郵便番号データ(3580件)をINSERT
総INSERT時間 = 2500ms
総INSERT時間 = 2625ms
総INSERT時間 = 2703ms

全国の全郵便番号データ(122635件)をINSERT
総INSERT時間 = 95031ms
総INSERT時間 = 95516ms
総INSERT時間 = 99188ms
クエリ

東京都の全郵便番号データ(3580件)の住所から「亀有」を含むものを抽出
クエリ時間 = 15ms
クエリ時間 = 16ms
クエリ時間 = 16ms

全国の全郵便番号データ(122635件)の住所から「亀有」を含むものを抽出
クエリ時間 = 297ms
クエリ時間 = 313ms
クエリ時間 = 313ms
※郵便番号データは2009/2のもの。
※最速のコーディング方法ではなく、一般的と思われるコーディング方法で試しました。

ダウンロード

サンプルソース [ Down ]


Copyright 2003-2010 yhira All Rights Reserved`
[Server] [Delphi Tips]
最終更新:2009/09/23 18:22:56