ntext 型、text 型、および image 型のデータの管理

重要な注意事項重要

この機能は、将来のバージョンの Microsoft SQL Server では削除される予定です。新しい開発作業では、この機能の使用を避け、現在この機能を使用しているアプリケーションは修正するようにしてください。代替のデータ型は varchar(max)、nvarchar(max)、および varbinary(max) です。詳細については、「大きな値のデータ型の使用」を参照してください。

SQL Server の ntext 型、text 型、および image 型には、最大 2 GB の非常に大きな 1 つの値を保持できます。1 つのデータ値は、通常の場合、アプリケーションが 1 回の操作で取得できるよりも大きくなります。クライアント側で利用できる仮想メモリより大きいこともあります。このため、これらの値を取得するには特殊な手順が必要です。

ntext 型、text 型、および image 型のデータ値が、4,000 文字の Unicode、8,000 文字の文字、または 8,000 バイトのバイナリ文字列よりも短い場合は、これらのデータ型より小さいデータ型の場合と同様に SELECT、UPDATE、および INSERT の各ステートメントで値を参照できます。たとえば、ntext 列の値が短い場合、nvarchar 列を参照するときと同じ方法で SELECT ステートメントの選択リストで参照できます。ただし、WHERE 句では ntext 列、text 列、または image 列を直接参照できないなどの制限があります。これらの列は、ISNULL、SUBSTRING、PATINDEX などの他のデータ型を返す関数のパラメータとして WHERE 句に、あるいは IS NULL、IS NOT NULL、LIKE の各式に含めることができます。

比較的大きなデータ値の処理

ntext 型、text 型、および image 型のデータ値がさらに大きくなった場合は、ブロック単位で処理する必要があります。Transact-SQL とデータベース API のどちらにも、ntext 型、text 型、および image 型のデータをアプリケーションがブロック単位で処理するための関数があります。

ntext 型、text 型、および image 型の比較的長い列を、データベース API を使用して次の共通の方法で処理します。

  • 長い列を読み取る場合、アプリケーションは ntext 列、text 列、または image 列を選択リストに含め、妥当な量のデータ ブロックを保持できる大きさのプログラム変数に列をバインドします。次にステートメントを実行し、API 関数またはメソッドを使用してデータを取得して、バインドした変数に一度に 1 ブロックずつ書き込みます。

  • 長い列を書き込む場合、アプリケーションは ntext 列、text 列、または image 列の値を格納する位置をパラメータ マーカー (?) で示して INSERT ステートメントまたは UPDATE ステートメントを実行します。パラメータ マーカー (ADO の場合はパラメータ) はデータ ブロックを保持できる大きさのプログラム変数にバインドされます。アプリケーションはループに移り、バインドされた変数に次のデータセットを移動してから、API 関数またはメソッドを呼び出してそのデータ ブロックを書き込みます。すべてのデータ値が書き込まれるまで、この手順を繰り返します。

text in row オプションの使用

SQL Server では、ユーザーはテーブルで text in row オプションを有効にして、text 型、ntext 型、または image 型のデータをそのデータ行に格納できます。

このオプションを有効にするには、オプション名に text in row、オプション値に on を指定して sp_tableoption ストアド プロシージャを実行します。text 型、ntext 型、または image 型のデータなどの BLOB (バイナリ ラージ オブジェクト) を行に格納できる既定の最大サイズは 256 バイトですが、最大値は 24 ~ 7000 の範囲で指定できます。既定値とは異なる最大サイズを指定するには、オプション値として範囲内の整数を指定します。

以下の条件を満たす場合に、text 型、ntext 型、または image 型の文字列がデータ行に格納されます。

  • text in row オプションが有効。

  • 文字列の長さが @OptionValue で指定した制限値より短い。

  • データ行に十分な領域がある。

BLOB 文字列がデータ行に格納される場合、text 型、ntext 型、または image 型の文字列を読み書きする速度は、文字列やバイナリ列を読み書きする速度と変わりません。SQL Server では、別のページにアクセスしなくても BLOB 文字列を読み書きできます。

text 型、ntext 型、または image 型の文字列が、指定された制限値より長かったり、その行で使用できる容量を超えている場合は、代わりにポインタが行に格納されます。ただし、BLOB 文字列を行に格納する場合の条件は引き続き適用されます。ただし、データ行にはポインタを格納するのに十分な領域が必要です。

詳細については、「sp_tableoption (Transact-SQL)」を参照してください。

テキスト ポインタの使用

text in row オプションが指定されている場合を除き、text 型、ntext 型、または image 型の文字列はデータ行の外部に格納されます。この場合、これらの文字列へのテキスト ポインタだけがデータ行に格納されます。テキスト ポインタは、複数の内部ポインタで構成されるツリーのルート ノードを指します。それらの内部ポインタは、text 型、ntext 型、および image 型の文字列が分割されて実際に格納されている各ページにマップされます。

SQL Server 2000 の行内テキスト ポインタは、以前のバージョンの SQL Server のテキスト ポインタとは異なります。行内テキスト ポインタは、BLOB データに対するファイル ハンドルのように機能します。一方、以前のテキスト ポインタは BLOB データへのアドレスのように機能します。このため、行内テキスト ポインタを使用する場合は、次の特性に注意してください。

重要な注意事項重要

行内テキストはカーソルで使用できますが、行内テキスト ポインタはカーソルでは使用できません。行内テキスト ポインタを含むカーソルを宣言すると、SQL Server からエラー 328 が返されます。

  1. データーベースでのトランザクションごとに最大 1,024 のアクティブな行内テキスト ポインタを使用できます。

  2. ロック

    あるユーザーがアクティブなテキスト ポインタを取得すると、SQL Server 2000 によりそのデータ行がロックされます。そのユーザーがテキスト ポインタを取得している限り、他のユーザーはその行に対して変更や削除ができません。このロックは、テキスト ポインタが無効になると解除されます。テキスト ポインタを無効にするには、sp_invalidate_textptr (Transact-SQL) を使用します。

    トランザクションの分離レベルが "READ UNCOMMITTED" の場合や、データベースが "読み取り専用" モードの場合は、テキスト ポインタを使用して BLOB 値を更新することはできません。

    データーベースが "シングル ユーザー モード" の場合は、SQL Server 2000 によりデータ行がロックされることはありません。

    説明のため、次のテーブルを用意します。

    CREATE TABLE t1 (c1 int, c2 text)
    EXEC sp_tableoption 't1', 'text in row', 'on'
    INSERT t1 VALUES ('1', 'a')
    

    次のトランザクションは成功します。

    INSERT t1 VALUES ('1','This is text.')
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    GO
    BEGIN TRAN
    DECLARE @ptr varbinary(16)
    SELECT @ptr = textptr(c2)
    FROM t1
    WHERE c1 = 1;
    READTEXT t1.c2 @ptr 0 5
    COMMIT TRAN
    GO
    

    次のトランザクションは失敗します。

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    GO
    BEGIN TRAN
    DECLARE @ptr varbinary(16)
    SELECT @ptr = textptr(c2)
    FROM t1
    WHERE c1 = 1
    WRITETEXT t1.c2 @ptr 'xx'
    COMMIT TRAN
    GO
    
  3. 期間

    行内テキスト ポインタは、トランザクション内でのみ有効です。トランザクションがコミットされると、テキスト ポインタは無効になります。

    トランザクション内でも、次のいずれかの操作が行われると、行内テキスト ポインタは無効になります。

    • 該当のセッションが終了した。

    • 同一のトランザクション内で該当のデータ行が削除された (その時点でロックされるため、他のトランザクションではデータ行を削除できません)。

    • 該当するテキスト ポインタを含むテーブルのスキーマが変更された。テキスト ポインタを無効にするスキーマ変更操作には、クラスタ化インデックスの作成や削除、テーブルの変更や削除、テーブルの切り捨て、sp_tableoption による text in row オプションの変更、および sp_indexoption の実行があります。

    前述の例を使用すると、次のスクリプトは以前のバージョンの SQL Server では機能しますが、SQL Server 2000 ではエラーになります。

    DECLARE @ptrval varbinary(16)
    PRINT 'get error here'
    SELECT @ptrval = TEXTPTR(c2)
    FROM t1
    WHERE c1 = 1
    READTEXT t1.c2 @ptrval 0 1
    

    SQL Server 2000 では、行内テキスト ポインタは必ずトランザクションの内部で使用してください。

    BEGIN TRAN
    DECLARE @ptrval varbinary(16)
    SELECT @ptrval = TEXTPTR(c2)
    FROM t1
    WHERE c1 = 1
    READTEXT t1.c2 @ptrval 0 1
    COMMIT
    
  4. NULL テキスト

    INSERT で生成された NULL テキストに対して行内テキスト ポインタを取得できます。これまでは、BLOB を NULL に更新しないとテキスト ポインタを取得できませんでした。

    たとえば、次のコードは SQL Server 7.0 では機能しませんが、SQL Server 2000 では機能します。

    SET TRANSACTION ISOLATION LEVEL READ COMMITTED
    GO
    INSERT INTO t1 VALUES (4, NULL)
    BEGIN TRAN
    DECLARE @ptrval VARBINARY(16)
    SELECT @ptrval = TEXTPTR(c2)
    FROM t1
    WHERE c1 = 4
    WRITETEXT t1.c2 @ptrval 'x4'
    COMMIT
    

    SQL Server 7.0 では、次のコードを使用する必要があります。

    INSERT INTO t1 VALUES (4, NULL)
    UPDATE t1 
       SET c2 = NULL 
       WHERE c1 = 4
    DECLARE @ptrval VARBINARY(16)
    SELECT @ptrval = TEXTPTR(c2)
    FROM t1
    WHERE c1 = 4
    WRITETEXT t1.c2 @ptrval 'x4'
    

次の表は、行内テキスト ポインタとその他のテキスト ポインタの相違点をまとめたものです。

相違点

行内テキスト ポインタ

その他のテキスト ポインタ

データベースのトランザクションごとに最大 1,024 のアクティブな行内テキスト ポインタを使用できます。

無制限。

ロック

ポインタが無効になるまで、データ行は S (共有) ロックされます。

トランザクションが "READ UNCOMMITTED" の場合や、データベースが "シングル ユーザー" モードまたは "読み取り専用" モードの場合は、ロックされません。

データ行はロックされません。

期間

トランザクションやセッションの終了時、行が削除されたとき、またはテーブルのスキーマが変更されたときには無効になります。

行が削除されると、無効になります。

NULL テキスト

NULL テキストの挿入後、すぐに取得できます。

更新しないと取得できません。

データベース API による ntext、text、または image データの使用

データベース API が ntext 型、text 型、および image 型のデータを処理するには、次の方法があります。

  • ADO

    ADO により、ntext、text、または image 型の列やパラメータを、Field オブジェクトまたは Parameter オブジェクトにマップできます。GetChunk メソッドを使用して一度に 1 ブロックずつデータを取得し、AppendChunk メソッドを使用して一度に 1 ブロックずつデータを書き込みます。

  • OLE DB

    OLE DB では、ntext 型、text 型、および image 型のデータをサポートするために、ISequentialStream インターフェイスが使用されます。ISequentialStream::Read メソッドは一度に 1 ブロックずつ長いデータを読み取ります。ISequentialStream::Write は一度に 1 ブロックずつ長いデータを書き込みます。詳細については、「BLOB と OLE オブジェクト」を参照してください。

  • ODBC

    ODBC には、SQL_WLONGVARCHAR (ntext)、SQL_LONGVARCHAR (text)、および SQL_LONGVARBINARY (image) など、大きなデータの ODBC データ型を処理するための "実行時データ" と呼ばれる機能があります。これらのデータ型はプログラム変数にバインドされます。長いデータを一度に 1 ブロックずつ取得するには、SQLGetData を呼び出します。長いデータを一度に 1 ブロックずつ送信するには SQLPutData を呼び出します。詳細については、「text 列と image 列の管理」を参照してください。

  • DB-Library

    DB-Library アプリケーションも ntext 列、text 列、および image 列をプログラム変数にバインドします。DB-Library 関数 dbtxtptr は、データベース内で長い列が出現する位置へのポインタを取得するのに使用します。dbreadtext は、長いデータを一度に 1 ブロックずつ読み取るのに使用します。dbwritetextdbupdatetextdbmoretext などの関数は、長いデータを一度に 1 ブロックずつ書き込むのに使用します。

    注意

    DB-Library を使用した行内テキストへのアクセスは、サポートされていません。

詳細については、「テキスト関数とイメージ関数 (Transact-SQL)」を参照してください。