範囲の指定
範囲でのレコードの制限 への移動
範囲を指定するには、互いに排他的な方法が 2 つあります。
- SetRangeStart および SetRangeEnd を使用して、開始値と終了値を別々に指定する
- SetRange を使用して両端を同時に指定する
範囲の開始値の設定
SetRangeStart 手続きを呼び出して、データセットを dsSetKey 状態にし、範囲の開始値リストの作成を開始します。SetRangeStart を呼び出すと、その後に続く Fields プロパティへの代入が、範囲の適用時に使用される開始インデックス値として扱われます。指定したフィールドを現在のインデックスに適用する必要があります。
たとえば、アプリケーションで Customers という名前の TSimpleDataSet コンポーネントを、CUSTOMER テーブルにリンクして使用していて、Customers データセットの各フィールドの永続フィールド コンポーネントを作成済みであるとします。CUSTOMER は、最初の列(CustNo)がインデックス付けされています。アプリケーションのフォームには、StartVal および EndVal という名前の 2 つの編集コンポーネントがあり、範囲の開始値と終了値を指定するのに使用します。次のコードが、範囲を作成して適用するのに使用できます。
with Customers do begin SetRangeStart; FieldByName('CustNo').AsString := StartVal.Text; SetRangeEnd; if (Length(EndVal.Text) > 0) then FieldByName('CustNo').AsString := EndVal.Text; ApplyRange; end;
Customers->SetRangeStart(); Customers->FieldValues["CustNo"] = StrToInt(StartVal->Text); Customers->SetRangeEnd(); if (!EndVal->Text.IsEmpty()) Customers->FieldValues["CustNo"] = StrToInt(EndVal->Text); Customers->ApplyRange();
このコードでは、Fields に値を代入する前に、EndVal に入力されたテキストが null ではないかチェックしています。StartVal に入力されたテキストが null の場合、すべての値は null より大きいので、データセットの先頭からのすべてのレコードが含まれます。しかし、EndVal に入力されたテキストが null の場合は、null より小さい値はないので、どのレコードも含まれません。
複数列インデックスでは、インデックスのすべてのフィールドに開始値を指定することも、一部のフィールドに開始値を指定することもできます。インデックスで使用されるフィールドに値を設定しないと、範囲の適用時に null 値と見なされます。範囲の開始値(または終了値)を指定しないと、そのドメインの最小限(または最大限)が使用されます。インデックスに存在しないフィールドに値を設定しようとすると、データセットで例外が発生します。
ヒント: データセットの先頭から開始するには、SetRangeStart の呼び出しを省略します。
範囲の開始値の指定を終了するには、SetRangeEnd を呼び出すか、範囲を適用するか取り消します。
範囲の終了値の設定
SetRangeEnd 手続きを呼び出して、データセットを dsSetKey 状態にし、範囲の終了値リストの作成を開始します。SetRangeEnd を呼び出すと、その後に続く Data.DB.TDataSet.Fields プロパティへの代入が、範囲の適用時に使用される終了インデックス値として扱われます。指定したフィールドを現在のインデックスに適用する必要があります。
警告: データセットの最終レコードで範囲を終了させる場合でも、範囲の終了値は必ず指定します。終了値を設定しないと、Delphi は範囲の終了値を null 値と見なします。終了値が null の範囲は、常に空です。
Data.DB.TDataSet.FieldByName メソッドを呼び出すと、簡単に終了値を代入できます。以下に例を示します。
with Contacts do begin SetRangeStart; FieldByName('LastName').AsString := Edit1.Text; SetRangeEnd; FieldByName('LastName').AsString := Edit2.Text; ApplyRange; end;
Contacts->SetRangeStart(); Contacts->FieldByName("LastName")->Value = Edit1->Text; Contacts->SetRangeEnd(); Contacts->FieldByName("LastName")->Value = Edit2->Text; Contacts->ApplyRange();
範囲の開始値の指定と同様、インデックスに存在しないフィールドに値を設定しようとすると、データセットで例外が発生します。
範囲の終了値の指定を終了するには、範囲を適用するか取り消します。
範囲の開始値と終了値の設定
範囲の境界を指定するのに SetRangeStart と SetRangeEnd を別々に呼び出す代わりに、SetRange 手続きを呼び出すと、一度の呼び出しで、データセットを dsSetKey 状態にして範囲の開始値と終了値を設定できます。
SetRange は、2 つの定数配列パラメータ(開始値のセットと終了値のセット)を取ります。たとえば次のステートメントでは、2 列インデックスに基づいて範囲を設定しています。
SetRange([Edit1.Text, Edit2.Text], [Edit3.Text, Edit4.Text]);
TVarRec StartVals[2]; TVarRec EndVals[2]; StartVals[0] = Edit1->Text; StartVals[1] = Edit2->Text; EndVals[0] = Edit3->Text; EndVals[1] = Edit4->Text; Table1->SetRange(StartVals, 1, EndVals, 1);
複数列インデックスでは、インデックスのすべてのフィールドに開始値と終了値を指定することも、一部のフィールドに開始値と終了値を指定することもできます。インデックスで使用されるフィールドに値を設定しないと、範囲の適用時に null 値と見なされます。インデックスの最初のフィールドの値を除外して、それに続くフィールドの値を指定するには、除外するフィールドに null 値を渡します。
データセットの最終レコードで範囲を終了させる場合でも、範囲の終了値は必ず指定します。終了値を設定しないと、データセットは範囲の終了値を null 値と見なします。開始範囲が終了範囲以上になるので、終了値が null の範囲は常に空です。
部分キーに基づいた範囲の指定
キーが 1 つ以上の文字列フィールドで構成されている場合、SetRange メソッドは部分キーをサポートします。たとえば、あるインデックスが LastName 列と FirstName 列に基づいている場合、次の範囲指定が有効です。
Contacts.SetRangeStart; Contacts['LastName'] := 'Smith'; Contacts.SetRangeEnd; Contacts['LastName'] := 'Zzzzzz'; Contacts.ApplyRange;
Contacts->SetRangeStart(); Contacts->FieldValues["LastName"] = "Smith"; Contacts->SetRangeEnd(); Contacts->FieldValues["LastName"] = "Zzzzzz"; Contacts->ApplyRange();
このコードでは、LastName が "Smith" 以上のすべてのレコードが範囲に含まれます。次のように値を指定することもできます。
Contacts['LastName'] := 'Sm';
Contacts->FieldValues["LastName"] = "Sm";
このステートメントでは、LastName が "Sm" 以上のレコードが含まれます。
境界値に一致するレコードの包含または除外
デフォルトでは、指定した範囲の開始値以上で、指定した範囲の終了値以下のすべてのレコードが範囲に含まれます。この動作は、KeyExclusive プロパティが制御します。KeyExclusive は、デフォルトでは False です。
必要な場合、データセットの KeyExclusive プロパティに True を設定すると、範囲の終了値に等しいレコードを除外できます。以下に例を示します。
Contacts.KeyExclusive := True; Contacts.SetRangeStart; Contacts['LastName'] := 'Smith'; Contacts.SetRangeEnd; Contacts['LastName'] := 'Tyler'; Contacts.ApplyRange;
Contacts->SetRangeStart(); Contacts->KeyExclusive = true; Contacts->FieldValues["LastName"] = "Smith"; Contacts->SetRangeEnd(); Contacts->FieldValues["LastName"] = "Tyler"; Contacts->ApplyRange();
このコードでは、LastName が "Smith" 以上で "Tyler" 未満のすべてのレコードが範囲に含まれます。