SQL からデータを取得するときにエラーが発生80020009

この記事は、SQL Serverからデータを取得するときに発生する80020009 エラーを解決するのに役立ちます。

元の製品バージョン: SQL Server
元の KB 番号: 175239

現象

SQL テーブルのデータを格納またはBlob型指定する Active Server Pages (ASP) ファイル内のレコードセットにアクセスすると、次のTextエラーが発生します。

Microsoft OLE DB Provider for ODBC Drivers エラー '80020009'

原因

次の条件により、エラーが発生する可能性があります。

テキスト/BLOB フィールドは、他の種類のフィールドの前の順序で選択されます。

解決方法

Microsoft SQL Server から BLOB フィールドを処理する場合は、結果セット内の BLOB 以外の列の右側にフィールドを配置する必要があります。 安全に行うには、列を左から右の順序で読み取る必要もあります。そのため、結果セットの最後の 2 つの列として 2 つの BLOB 列がある場合は、最初の列を読み取り、2 番目の列を読み取ります。 逆の順序で読み取らないでください。

フィールド選択の正しい順序を示すために、Visual InterDev プロジェクトに新しい ASP ページを作成し、空白の ASP ページに次のコードを貼り付けます。 SQL Serverに接続するように接続文字列を変更します。

注:

このコードを実行する前に、Username=<username> と PWD=<strong password> を正しい値に変更する必要があります。 ユーザー ID に、データベースでこの操作を実行するための適切なアクセス許可があることを確認します。

 <%@ Language=VBScript %>
 <HTML>
     <BODY bgcolor=white>
         <%
             Set cn = Server.CreateObject("ADODB.Connection")
             Set rs = Server.CreateObject("ADODB.Recordset")'Open the connection.
             cn.Open "dsn=yoursystemdsn;Username=<username>;PWD=<strong password>;database=pubs;"
    
            'Open the recordset.

            'Notice that the Blob field, pr_info, is last in the field order.

            rs.Open "select pub_id, pr_info from pub_info", cn

            While Not rs.EOF

            Response.Write "<P>PR Info:<P>" & rs("pr_info")
             Response.Write "<P>That was the PR Info for PubID " & 
             rs("pub_id")
             rs.MoveNext
             Wend
         %>
     </BODY>
 </HTML>

状態

この動作は仕様です。 ただし、SQL Serverに Mdac 2.1 sp2 以降を 3.7 ドライバー以降で使用する場合は発生しません。

詳細

SQL Serverは、ネットワーク上のデータを送信し、クライアントは基本的にネットワーク ネットワーク上で順次読み取られたビットストリームを受信しています。 バインドされた列を使用すると (つまり、値をローカル メモリ バッファーにコピーしてキャッシュできます)、ドライバーはそれらの列のデータをメモリ バッファーに転送します。 データがローカル バッファーに格納されたら、任意の順序でデータを読み取ります。 そのため、(BLOB ではなく) すべての列がバインドされている場合は、結果列を任意の順序で読み取ることができます。

BLOB 列を含めると、列の長さは約 2 ギガバイトになり、データ アクセス ライブラリは通常、これらの列をバインドしません。多くの場合、ドライバーは取得されるまで BLOB のサイズを正確に判断できないためです。 また、データ アクセス ライブラリは通常、BLOB データのキャッシュを回避します。これは大量のメモリを消費し、データ アクセス ライブラリ内の両方にキャッシュするため、アプリケーションは非効率的です。 データ アクセス ドライバーは、BLOB 列の内容を返すように要求された場合、要求された列を読み取る前にシーケンシャル データ ストリームを取得する必要があるため、通常、要求された BLOB 列の前にあるバインドされていない列を破棄します。 そのため、データの取得方法と一致するため、結果セットを左から右に読み取る方が効率的です。

注:

ここでは、SQL Serverの動作について説明します。 Oracle と他のクライアント/サーバー DBMS は同じことを行うことができますが、必須ではありません。

おそらく、Text 列を使用しないようにすることをお勧めします。 SQL Serverは 2K チャンクで領域を割り当てるので、テキストの長さが小さい場合、Text 列を使用するとストレージが非効率的に使用される可能性があります。 また、トランザクション ログのダンプに時間がかかるため、バックアップ時間も影響を受けます。 多くの場合、既存のテーブルの PK、チャンク番号列、列を含む別のテーブルを varchar (255) 作成することをお勧めします。 テキストを必要な数の 255 文字のチャンクに分割し、チャンクがあるのと同じ数の行を新しいテーブルに挿入します。 通常、ストレージをより効率的に使用し、バックアップをはるかに高速に使用できるため、コーディング時間を増やす価値があります。