[SQL ODBC]「text、ntext、または image ポインター値は、指定した列名と競合しています。」エラーが発生する

 

佐藤 靖典
SQL Developer Support Engineer

 

みなさん、こんにちは。

今回は、SQL Server の varbinary(max) 型の列に対して書き込みを行おうとしたときに遭遇する可能性のある事象と対処方法を紹介します。

[1] 事象

Windows 同梱の SQL Server ODBC Driver を使用して、400KB 以上のデータを varbinary(max) 型の列に書き込みを行おうとすると、次のエラーが発生します。

日本語のエラー メッセージ
[Microsoft][ODBC SQL Server Driver][SQL Server]text、ntext、または image ポインター値は、指定した列名と競合しています。

英語のエラー メッセージ
[Microsoft][ODBC SQL Server Driver][SQL Server]The text, ntext, or image pointer value conflicts with the column name specified.

[2] 詳細

ODBC API を使用してパラメータ クエリを実行する場合、400 KB (409600 バイト) 以上の長いバイナリ値をパラメータ値に渡すと、そのパラメータのデータ型には、C データ型に対して SQL_C_BINARY を、SQL データ型に対して SQL_LONGVARBINARY を指定します。SQL Server ODBC Driver は、このパラメータ定義に対応する SQL Server のデータ型を image 型と想定するため、image 型の更新のために用意されている WRITETEXT ステートメントを SQL Server に発行します。
しかしながら、SQL Server では、WRITETEXT ステートメントは text、ntext、image 型用に用意している機能であるため、varbinary(max) に対して使用するとエラーとなります。

例えば、ADO から OLE DB Provider for ODBC (MSDASQL) + SQL Server ODBC Driver を使用して SQL Server にアクセスする場合、上記のパラメータ定義が SQL Server ODBC Driver に渡されるため、同エラーが発生します。

本動作は、SQL Server ODBC Driver の制限です。
SQL Server ODBC Driver は、varbinary(max) 型のサポート以前に設計されました。

[3] 対処方法

varbinary(max) 型の列に書き込みを行うには、以下のいずれかを使用します。

(a) ODBC Driver 11 for SQL Server (ダウンロードはこちら)
(b) SQL Server Native Client 10.0 以上のバージョン (SQL Server Native Client 11.0 (SQL Server 2012 SP2 Native Client) のダウンロードはこちら)
(c) OLE DB Provider for SQL Server

補足
varbinary(max) の列データの更新のために、SQL Server Native Client 10.0 から製品内部で WRITETEXT の代わりに UPDATE ステートメントを発行するように対応致しました。
OLE DB Provider for SQL Server は、varbinary(max) 型のサポート以前に設計されましたが、製品内部で UPDATE ステートメントを発行しています。

弊社では最新のコンポーネントをご利用いただくことを推奨しているため、ODBC ドライバとしては ODBC Driver 11 for SQL Server、OLE DB プロバイダとしては SQL Server Native Client 11.0 をお奨めします。これらを利用いただく際の留意点は別途インストールいただく必要がある事です。Windows 同梱の機能を使用したい場合は、(c) の OLE DB Provider for SQL Server をご利用ください。

推奨されるデータアクセス コンポーネントは、英語版となりますが、次のページをご参照ください。随時アップデートしております。

Data Access Technologies Road Map

[4] 事象を再現するコード

テスト テーブル

CREATE TABLE TestTBL(   col1 int IDENTITY(1, 1) PRIMARY KEY,   col2 varbinary(max) )

VBA のテスト コード

Dim fileNumber As Integer Dim filePath As String Dim fileSize As Long Dim binData() As Byte      Dim Cn As New ADODB.Connection Dim Rs As New ADODB.Recordset Dim cnnString As String Dim sqlString As String          filePath = "C:\Work\bigsize.xlsx"      ' SQL Server ODBC Driver の利用 (エラーが発生します。) cnnString = "Driver={SQL Server};Server=dbserver01;Database=testdb;Trusted_Connection=Yes;"      ' ODBC Driver 11 for SQL Server の利用 (正常動作します。) 'cnnString = "Driver={ODBC Driver 11 for SQL Server};Server=dbserver01;Database=testdb;Trusted_Connection=Yes;"      ' SQL Server Native Client 11 の利用 (正常動作します。) 'cnnString = "Provider=SQLNCLI11;Server=dbserver01;Database=testdb;Trusted_Connection=Yes;"      ' OLE DB Provider for SQL Server の利用 (正常動作します。) 'cnnString = "Provider=SQLOLEDB;Server=dbserver01;Database=testdb;Trusted_Connection=Yes;"      sqlString = "SELECT * FROM TestTBL"      fileNumber = FreeFile() Open filePath For Binary Access Read As #fileNumber fileSize = LOF(fileNumber)      ReDim binData(fileSize - 1) As Byte Get fileNumber, , binData() Close #fileNumber      Cn.Open cnnString Cn.CursorLocation = adUseClient Rs.Open sqlString, Cn, adOpenKeyset, adLockOptimistic      With Rs     .AddNew     .Fields("col2").Value = binData()     .Update ' ここでエラーが発生します。 End With      Rs.Close Cn.Close