
InterBase と PostgreSQL が、配列フィールドをサポートしていることをご存知でしょうか?これらのデータベースの配列フィールドの読み書き方法は、必ずしも明確ではありません。Delphi や C++ 開発者から、困っていることがあり、それを実現する方法を知りたいというメールを頻繁に受け取ることがあります。最近受け取ったメールの1つは、データベースで配列フィールドを正しく表示・更新する方法に関するものでした。私自身も少し不安だったので調べてみましたが、メールを送ってくれた開発者と相談して、完璧に動作することを確認しました。この記事では、Delphi と FireDAC の力を借りてこれを実現する方法と、ダウンロードして配列を実際に試すことができる便利なデモのコードを紹介します。配列フィールドはDBMS間で広くサポートされているわけではないことに注意してください。MySQLもSQL Serverもサポートしていません。
Table of Contents
データベースの配列フィールドとは?
InterBase(InterBase)の配列フィールドは、その名前が示すように、単一の値ではなく、複数の値を含むことができます。これらの値はすべて、整数、文字など、同じ型である必要がありますが、多次元にすることができます。残念ながら、Star Trekのような多次元配列ではありません。integer[4][128]
のような、128個の整数が4つ並んだ配列を使用できるというだけです。 InterBase は長年にわたり配列フィールドをサポートしており、配列フィールドをサポートした最初のデータベースの 1 つです。

上記のIBConsole の画像でわかるように、フィールド MY_ARRAY
は12個の要素を含む配列フィールドです。InterBaseではこのようにシンプルです。上記のテーブルをInterBaseで作成するためのSQLは以下の通りです。
1 2 3 4 5 6 |
CREATE TABLE TABLE_WITH_ARRAY ( THE_YEAR INTEGER NOT NULL, MY_ARRAY INTEGER[1:12] , CONSTRAINT UNIQUE_YEAR UNIQUE (THE_YEAR) ); |
この表をデモプロジェクトで使用し、TChart コンポーネント(Steema 製)を使って、12ヶ月連続の棒グラフを表示します。Embarcadero版は無料で配布されているので、RAD Studio には既にインストールされていると思います。
データベースの配列フィールドを使用する理由
リレーショナルデータベースシステムでは、配列フィールドは直感に反するかもしれません。リレーショナルデータベースシステムでは、データベース正規化といった手法が好まれ、他のテーブルへの参照を持つテーブルが好まれる傾向にあります。他のテーブルにリンクする参照フィールドを持つ形式は、データを簡素化および抽象化するために役立ちますが、場合によっては複雑さを生じ、外部キーや クエリによる結合、カスケード更新などを使用する必要が生じることもあります。グラフ上に一連のデータポイントを描く場合など、実際のレコード自体に値の配列があれば十分な場合もあります。

配列フィールドは、もちろん、それだけではありません。相互に関連するあらゆる種類のデータを格納し、それらをすべて1か所(リンクされたレコードではなく、実際のレコード)にまとめたい場合に非常に便利です。「その他の電話番号」フィールドや「以前のパスワードハッシュ」(N回の反復処理内での再利用を防ぐため)、その他同様のコレクションに配列フィールドが使用されているのを目にしたことがあります。
PostgreSQL で配列フィールド型を定義するには?
InterBase は、上記で示した方法で配列を定義します。12 要素の配列フィールド型の場合、範囲は [1:12]
と定義されるため、最初の要素は [1]
、最後の要素は [12]
となります。PostgreSQL の配列も同様ですが、この記事の執筆時点では、確定的な配列添字を許可する構文があるにもかかわらず、PostgreSQL はそれを強制せず、実際には無視 するため、オープン配列として動作します。便利ですが、少し間違っている気がします。

PostgreSQL で配列フィールドを定義するには、PGAdmin を使用します。

そのSQLは以下の通りです。 the_minutiae
という配列フィールドが作成されます。これは整数値の配列です。
1 2 3 4 5 6 |
CREATE TABLE IF NOT EXISTS public.table_with_array ( the_person character varying(30) COLLATE pg_catalog."default" NOT NULL, the_minutiae integer[], CONSTRAINT table_with_array_pkey PRIMARY KEY (the_person) ) |
この表を使用します。デモプロジェクトでは、人の指紋の「特徴点」を表示するシミュレーションを行います。特徴点とは、渦巻き状の模様やアーチ状の模様など、指紋のパターンに特有の特徴です。面白い情報: コアラの指紋は人間の指紋とほとんど区別がつきません。🐨
InterBase の配列フィールドの読み取りと更新方法
デモプロジェクトではその方法を紹介していますが、ここでは詳細を簡単に説明します。接続の作成には FireDAC を使用し、配列フィールドを含むデータベーステーブルを管理するために FDTable を使用しました。

永続フィールドを追加しました。これにより、LiveBindingsを使用したビジュアルコントロールへのリンクが容易になります。


InterBase の配列フィールドに書き込むには?
これらの永続フィールドを作成してしまえば、あとは非常に簡単です。ユーザーが「fill with test data」ボタンをクリックしたときに実行されるコードを以下に示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
procedure TForm1.FillTestDataButtonClick(Sender: TObject); begin if not FDConnection1.Connected then ActivateDatabase; if FDConnection1.Connected then begin var sCaption: string := FillTestDataButton.Caption; CenterPanel.Visible := False; try ChangeTablesActiveStatus(False); FDQuery1.Sql.Text := 'TRUNCATE TABLE TABLE_WITH_ARRAY'; // Fastest way to empty the table FDQuery1.ExecSQL; UpdateTable.Active := True; UpdateTable.DisableControls; // prevent UI updates from slowing down our work for var TheYear := 1996 to 2034 do begin UpdateTable.Append; FillTestDataButton.Caption := TheYear.ToString; Application.ProcessMessages; UpdateTableTHE_YEAR.AsInteger := TheYear; for var TheMonth := 0 to 11 do UpdateTableMY_ARRAY.FieldValues[TheMonth] := Random(250); UpdateTable.Post; end; finally UpdateTable.EnableControls; UpdateTable.Active := False; ChangeTablesActiveStatus(True); end; FillTestDataButton.Caption := sCaption; CenterPanel.Visible := True; end; end; |
必要にに応じて他の方法もありますが、これはかなり高速です。数千件のレコードを一度に更新する場合は、ArrayDMLなどの技術を活用したクエリの作成を検討する必要があります。同僚のStephen Ballが、この点についてこちらで書いています: https://delphiaball.co.uk/2016/04/29/interbase-array-fields-firedac/ DockWikiにも記事があります。 配列 DML コマンドのパフォーマンス(FireDAC)
InterBase の配列フィールドの読み取り方法
上記のようにフィールドを定義すれば、InterBase の配列フィールドを読み取るための Delphi の実際のコードは簡単です。FieldValues
プロパティを使用します。以下は私のサンプルアプリからの抜粋です。InterBase では配列を [1:12]
と定義していますが、コード内のフィールドのインデックス値は 0 から始まることに注意してください。したがって、配列の値 1 は FieldValues[0]
です。
1 2 3 4 5 6 7 8 |
procedure TForm1.UpdateChart; begin Chart1.Title.Caption := ListTableTHE_YEAR.Value.ToString; Chart1.Series[0].Clear; var FS := TFormatSettings.Create; for var TheMonth := 0 to 11 do Chart1.Series[0].AddXY(TheMonth, ListTableMY_ARRAY.FieldValues[TheMonth], FS.ShortMonthNames[Succ(TheMonth)]); end; |
PostgreSQL 配列フィールドの読み取り方法
PostgreSQL 配列フィールドを読み取る最も簡単な方法は、TFDMemtable を使用することです。 PostgreSQL固有のSQL DML拡張機能を使用してこれを行う方法は他にもありますが、ここではFireDACのメモリテーブルを使用してその方法を示しました。

ListTable
という FDTable を作成しました(これは TListBox
の内容を操作するためです)。このテーブルは、配列フィールドを含むデータベース内のテーブルにリンクされています。次に、永続フィールド the_person
と the_minutiae
を作成しました。さらに、FireDAC メモリテーブルを追加し、DataSetField
プロパティを ListTable の永続フィールド the_minutiae
を指すように設定しました。これにより、ユーザーまたはコードが ListTable
FDTable
を別のレコードに移動するたびに、メモリテーブルが PostgreSQL 配列フィールドの配列内容で埋め尽くされるようになります。クールですよね? 😎
これで、通常の FireDAC テーブルと同じように内容を読み取ることができます。
1 2 3 4 5 6 7 |
while not FDMemTable1.Eof do begin LString := LString + LComma + FDMemTable1the_minutiae.AsString; LComma := ','; DrawDots; FDMemTable1.Next; end; |
PostgreSQL 配列フィールドを含むテーブルにデータを書き込む方法
繰り返しになりますが、PostgreSQL 配列フィールドへの書き込み方法は複数あります。私のデモでは、FireDAC クエリコンポーネントと SQL 文を使用して書き込みを行うことにしました。非常に簡単です。PostgreSQL 固有の関数や FireDAC 配列 DML を使用することもできますが、クエリの方がはるかに理解しやすいです。
1 2 3 4 5 6 7 8 9 10 11 12 |
FDUpdateQuery.SQL.text := 'insert into TABLE_WITH_ARRAY values (:person, :mins)'; FDUpdateQuery.Params[1].ArrayType := atTable; FDUpdateQuery.Params[1].ArraySize := 24; // TFDParam.ArraySize must be set to array size for var PersonNumber := 1 to 128 do begin FillTestDataButton.Caption := PersonNumber.ToString; Application.ProcessMessages; FDUpdateQuery.Params[0].AsString := 'Fake person ' + Format('%.3d', [PersonNumber]); for var Minutiae := 0 to 23 do FDUpdateQuery.Params[1].Values[Minutiae] := Random(150); FDUpdateQuery.ExecSQL; end; |
InterBase の配列フィールドと PostgreSQL の配列フィールドの読み込みと書き込みの完全な例はどこで入手できますか?
配列フィールドを含むデータベーステーブルの読み込みと書き込みの完全な動作例を含む 2 つのリポジトリを作成しました。
InterBase の例はこちらです: https://github.com/checkdigits/db_arrray_test
PostgreSQLの例はこちらです: https://github.com/checkdigits/db_arrray_test_PostgreSQL
デモを確認する際のヒント:Interbase(db_arrray_test)
- TeeChartをインストールするには、ツール|機能の管理でインストーラを起動し、技術セクションのTeeChart Standardを選択して適用します
- VCL Windows Style – Windows11 Impressive DarkおよびLightが使用されています(GetItで入手可能)。
- Embarcadero版のTChartを利用する場合、TeeChart Standard VCL Componentsを利用するのでプロジェクトオプションのパッケージから有効にしてください。
- Embarcadero版のTChartを利用する場合、上記を設定後、Marks.OnTopプロパティのエラーが発生した場合は「全て無視」を選択してください。
デモを確認する際のヒント:PostgreSQL(db_arrray_test_PostgreSQL)
- フォームのFDPhysPgDriverLink1のVenderLibを環境に合わせて設定します。
- コード中のPostgreSQLへの接続パラメータ定数を環境に合わせて設定します。
本ブログ記事は、Ian Barker 氏の「How To Read And Write Array Field Types In PostgreSQL and InterBase」の抄訳です。

ぜひ RAD Studio の無料トライアル版を今すぐダウンロードして、Windows、macOS、Linux、iOS、Android で動作するクロスプラットフォームアプリを単一のコードベースから作成できる、最も高速で簡単、そして効率的な方法である理由を実感してください。
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition