レコードセットの操作

Recordset オブジェクトには、結果セット内のデータの順序を並べ替えたり、指定した条件に基づいて特定のレコードを検索したり、インデックスを使用して検索操作を最適化したりするための組み込み機能があります。 これらの機能を使用できるかどうかは、プロバイダーによって異なります。場合によっては、Index プロパティの場合など、データ ソース自体の構造が異なります。

データの配置

多くの場合、Recordset 内のデータを並べ替える最も効率的な方法は、結果を返すために使用する SQL コマンドで ORDER BY 句を指定することです。 ただし、既に作成されている Recordset 内のデータの順序を変更する必要がある場合があります。 Sort プロパティを使用すると、Recordset の行の走査順序を設定できます。 さらに、Filter プロパティは、行を走査するときにアクセスできる行を決定します。

Sort プロパティは、並べ替える Recordset 内のフィールド名を示す 文字列 値を設定または返します。 各名前はコンマで区切られ、必要に応じてスペースとキーワード ASC(フィールドを昇順で並べ替える)または DESC(フィールドを降順で並べ替える)に続くことがあります。 既定では、キーワードが指定されていない場合、フィールドは昇順で並べ替えられます。

データは物理的に再配置されず、インデックスで指定された順序でアクセスされるため、並べ替え操作は効率的です。

Sort プロパティを使用するには、CursorLocation プロパティを adUseClient 設定する必要があります。 インデックスがまだ存在しない場合は、Sort プロパティで指定されたフィールドごとに一時インデックスが作成されます。

Sort プロパティを空の文字列に設定すると、行が元の順序にリセットされ、一時インデックスが削除されます。 既存のインデックスは削除されません。

たとえば、Recordset に、firstName middleInitial、および lastName という名前の 3 つのフィールド含まれているとします。 Sort プロパティを文字列 "lastName DESC, firstName ASC" に設定します。これにより、Recordset が姓を降順で、名を昇順で並べ替えられます。 中央のイニシャルは無視されます。

並べ替え条件文字列で参照されるフィールドは、"ASC" または "DESC" という名前にすることはできません。これらの名前は、ASC および DESC キーワード 競合するためです。 Recordsetを返すクエリで、AS キーワードを使用して、競合する名前のフィールドに別名を付けます。

レコードセット フィルター処理の詳細については、このトピックで後述する「結果のフィルター処理」を参照してください。

特定のレコードの検索

ADO には、Recordset内の特定のレコードを検索するための Find メソッドと Seek メソッドが用意されています。 Find メソッドは、さまざまなプロバイダーでサポートされていますが、1 つの検索条件に制限されています。 Seek メソッドは、複数の条件での検索をサポートしていますが、多くのプロバイダーではサポートされていません。

フィールドのインデックスを使用すると、Recordset オブジェクトの Find メソッドと Sort プロパティと Filter プロパティのパフォーマンスを大幅に向上させることができます。 動的 Optimize プロパティを設定することで、Field オブジェクトの内部インデックスを作成できます。 この動的プロパティは、CursorLocation プロパティを adUseClient 設定すると、Field オブジェクトの Properties コレクションに追加されます。 このインデックスは ADO の内部的なインデックスです。このインデックスにアクセスしたり、他の目的で使用したりすることはできません。 また、このインデックスは、Recordset オブジェクトの Index プロパティとは異なります。

Find メソッドは、Recordsetの列 (フィールド) 内の値をすばやく検索します。 列の Find メソッドの速度を向上させるには、Optimize プロパティを使用してインデックスを作成します。

Find メソッドは、検索を 1 つのフィールドの内容に制限します。 Seek メソッドでは、インデックスがあり、その他の制限も必要です。 インデックスの基礎ではない複数のフィールドを検索する必要がある場合、またはプロバイダーがインデックスをサポートしていない場合は、Recordset オブジェクトの Filter プロパティを使用して結果を制限できます。

見つける

Find メソッドは、Recordset で、指定した条件を満たす行を検索します。 必要に応じて、検索の方向、開始行、および開始行からのオフセットを指定できます。 条件が満たされた場合、現在の行位置は見つかったレコードに設定されます。それ以外の場合、位置は検索方向に応じて、Recordsetの末尾 (または開始) に設定されます。

条件には、単一列名のみを指定できます。 言い換えると、このメソッドは複数列の検索をサポートしていません。

条件の比較演算子には、">" (より大きい)、"<" (より小さい)、"=" (等しい)、">=" (以上)、"<=" (以下)、"<>" (等しくない)、または "LIKE" (パターン マッチング) を指定できます。

条件値には、文字列、浮動小数点数、または日付を指定できます。 文字列値は、単一引用符または "#" (数値記号) 記号 ("state = 'WA'" や "state = #WA#" など) で区切られます。 日付の値は、"#" (数値記号) 記号 ("start_date > #7/22/97#" など) で区切られます。

比較演算子が "like" の場合、文字列値にアスタリスク (*) を含め、任意の文字または部分文字列の 1 つ以上の出現箇所を見つけることができます。 たとえば、"state like 'M*'" は Maine と Massachusetts に一致します。 先頭と末尾のアスタリスクを使用して、値に含まれる部分文字列を検索することもできます。 たとえば、"state like '*as*'" は、アラスカ、アーカンソー、およびマサチューセッツ州と一致します。

アスタリスクは、前に示したように、抽出条件文字列の末尾でのみ、または抽出条件文字列の先頭と末尾の両方で一緒に使用できます。 先頭のワイルドカード ('*str') または埋め込みワイルドカード ('s*r') としてアスタリスクを使用することはできません。 これによりエラーが発生します。

検索とインデックス

基になるプロバイダーが Recordset オブジェクトのインデックスをサポートしている場合は、Index プロパティと共に Seek メソッドを使用します。 Supports(adSeek) メソッドを使用して、基になるプロバイダーが Seekをサポートしているかどうかを判断し、Supports(adIndex) メソッドを使用して、プロバイダーがインデックスをサポートしているかどうかを判断します。 (たとえば、OLE DB Provider for Microsoft Jet では、SeekIndexがサポートされます)。

Seek 目的の行が見つからない場合、エラーは発生せず、行は Recordsetの末尾に配置されます。 このメソッドを実行する前に、Index プロパティを目的のインデックスに設定します。

このメソッドは、サーバー側カーソルでのみサポートされます。 Recordset オブジェクトの CursorLocation プロパティ値が adUseClient 場合、Seek はサポートされません。

このメソッドは、Recordset オブジェクトが CommandTypeEnum の値として adCmdTableDirectで開かれている場合にのみ使用できます。

結果のフィルター処理

Find メソッドは、検索を 1 つのフィールドの内容に制限します。 Seek メソッドでは、インデックスがあり、その他の制限も必要です。 インデックスの基礎ではない複数のフィールドを検索する必要がある場合、またはプロバイダーがインデックスをサポートしていない場合は、Recordset オブジェクトの Filter プロパティを使用して結果を制限できます。

Filter プロパティを使用して、Recordset オブジェクト内のレコードを選択的にスクリーン アウトします。 フィルター処理された Recordset が現在のカーソルになります。つまり、フィルター が削除されるまで、フィルター 条件を満たしていないレコードは、Recordset で使用できなくなります。 現在のカーソルに基づいて値を返すその他のプロパティ (AbsolutePositionAbsolutePageRecordCountPageCountなど) が影響を受けます。 これは、Filter プロパティを特定の値に設定すると、現在のレコードが新しい値を満たす最初のレコードに移動するためです。

Filter プロパティは、バリアント引数を受け取ります。 この値は、条件文字列、FilterGroupEnum 定数、またはブックマークの配列という、Filter プロパティを使用する 3 つのメソッドのいずれかを表します。 詳細については、このトピックで後述する「抽出条件文字列を使用したフィルター処理、定数によるフィルター処理、およびブックマークによるフィルター処理」を参照してください。

手記

選択するデータがわかっている場合は、通常、Filter プロパティに依存するのではなく、結果セットを効果的にフィルター処理する SQL ステートメントを使用して Recordset を開く方が効率的です。

Recordsetからフィルターを削除するには、adFilterNone 定数を使用します。 Filter プロパティを長さ 0 の文字列 ("") に設定すると、adFilterNone 定数を使用する場合と同じ効果があります。

抽出条件文字列を使用したフィルター処理

抽出条件文字列は、FieldName 演算子値 (たとえば、"LastName = 'Smith'") の形式の句で構成されます。 複合句を作成するには、個々の句を AND で連結する(たとえば "LastName = 'Smith' AND FirstName = 'John'")方法と、OR で連結する(たとえば "LastName = 'Smith' OR LastName = 'Jones'")方法があります。 条件文字列には、次のガイドラインを使用します。

  • FieldName は、Recordsetの有効なフィールド名である必要があります。 フィールド名にスペースが含まれている場合は、名前を角かっこで囲む必要があります。

  • 演算子 は、<><=>=<>=、または LIKE のいずれかである必要があります。

  • は、フィールド値 ('Smith'#8/24/95#12.345$50.00など) を比較する値です。 文字列を含む単一引用符 (') と、日付を含むポンド記号 (#) を使用します。 数値の場合は、小数点、ドル記号、指数表記を使用できます。 演算子 が LIKE 場合、Value はワイルドカード文字を使用できます。 アスタリスク (*) とパーセント記号 (%) ワイルドカード文字のみを使用でき、文字列の最後の文字にする必要があります。 を null にすることはできません。

    手記

    フィルター Valueに単一引用符 (') を含めるには、2 つの単一引用符を使用して 1 つを表します。 たとえば、O'Malleyでフィルター処理するには、条件文字列を "col1 = 'O''Malley'"する必要があります。 フィルター値の先頭と末尾の両方に単一引用符を含めるには、文字列をシャープ記号 (#)で囲みます。 たとえば、'1'でフィルター処理するには、条件文字列を "col1 = #'1'#"する必要があります。

ANDORの間に優先順位はありません。 句を括弧内にまとめることができます。 ただし、次のように、OR によって結合された句をグループ化し、AND を使用してグループを別の句に結合することはできません。

(LastName = 'Smith' OR LastName = 'Jones') AND FirstName = 'John'  

代わりに、次のようにこのフィルターを構築します。

(LastName = 'Smith' AND FirstName = 'John') OR (LastName = 'Jones' AND FirstName = 'John')  

LIKE 句では、パターンの先頭と末尾 (たとえば、LastName Like '*mit*') またはパターンの末尾 (LastName Like 'Smit*'など) にのみワイルドカードを使用できます。

定数を使用したフィルター処理

次の定数は、レコードセット のフィルター処理に使用できます。

定数 説明
広告フィルター対象レコード 最後の DeleteResyncUpdateBatchまたは CancelBatch 呼び出しの影響を受けるレコードのみを表示するためのフィルター。
adFilterConflictingRecords 最後のバッチ更新に失敗したレコードを表示するためのフィルター。
adFilterFetchedRecords 現在のキャッシュ内のレコード (つまり、データベースからレコードを取得する最後の呼び出しの結果) を表示するためのフィルター。
adFilterNone する 現在のフィルターを削除し、表示するすべてのレコードを復元します。
広告フィルタ保留中のレコード 変更されたが、まだサーバーに送信されていないレコードのみを表示するためのフィルター。 バッチ更新モードにのみ適用されます。

フィルター定数を使用すると、バッチ更新モード中の個々のレコードの競合を簡単に解決できます。たとえば、次の例に示すように、最後の UpdateBatch メソッド呼び出し中に影響を受けたレコードのみを表示できます。

Attribute VB_Name = "modExaminingData"

ブックマークを使用したフィルター処理

最後に、ブックマークのバリアント配列を Filter プロパティに渡すことができます。 結果のカーソルには、ブックマークがプロパティに渡されたレコードのみが含まれます。 次のコード例では、ProductName フィールドに "B" が含まれる Recordset 内のレコードからブックマークの配列を作成します。 次に、配列を Filter プロパティに渡し、結果としてフィルター処理された Recordsetに関する情報を表示します。

'BeginFilterBkmk  
Dim vBkmkArray() As Variant  
Dim i As Integer  
  
'Recordset created using "SELECT * FROM Products" as command.  
'So, we will check to see if ProductName has a capital B, and  
'if so, add to the array.  
i = 0  
Do While Not objRs.EOF  
    If InStr(1, objRs("ProductName"), "B") Then  
        ReDim Preserve vBkmkArray(i)  
        vBkmkArray(i) = objRs.Bookmark  
        i = i + 1  
        Debug.Print objRs("ProductName")  
    End If  
    objRs.MoveNext  
Loop  
  
'Filter using the array of bookmarks.  
objRs.Filter = vBkmkArray  
  
objRs.MoveFirst  
Do While Not objRs.EOF  
    Debug.Print objRs("ProductName")  
    objRs.MoveNext  
Loop  
'EndFilterBkmk  

レコードセットの複製を作成する

Clone メソッドを使用して、レコードセット オブジェクトの複数の複製を作成します。特に、特定のレコードセット内で複数のカレントレコードを維持したい場合に、このメソッドを使用します。 Clone メソッドの使用は、元のオブジェクトと同じ定義を持つ新しい Recordset オブジェクトを作成して開くよりも効率的です。

新しく作成された複製の現在のレコードは、最初のレコードに最初に設定されます。 複製された Recordset 内の現在のレコード ポインターが、元のレコードと同期されていないか、元のレコード ポインターと同期されません。 各 Recordset内で個別に移動できます。

1 つの Recordset オブジェクトに加えた変更は、カーソルの種類に関係なく、すべての複製に表示されます。 ただし、元の RecordsetRequery を実行した後、複製は元の複製と同期されなくなります。

元の Recordset を閉じてもそのコピーは閉じず、逆にコピーを閉じても元のものや他のコピーも閉じません。

Recordset オブジェクトは、ブックマークをサポートしている場合にのみ複製できます。 ブックマーク値は交換可能です。つまり、1 つの Recordset オブジェクトからのブックマーク参照は、複製内の同じレコードを参照します。