DELETE ステートメントを使用して SQL Server 内のテーブルからデータを削除した後、テーブルが使用する領域は完全には解放されません。

この記事は、DELETE ステートメントを使用してテーブルからすべてのデータを削除した後に、テーブルで使用される問題を解決するのに役立ちます。

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

現象

Microsoft SQL Server で DELETE ステートメントを使用してテーブルからデータを削除すると、テーブルで使用される領域が完全に解放されないことに気付く場合があります。 その後、データベースにデータを挿入しようとすると、次のエラー メッセージが表示されることがあります。

'PRIMARY' ファイル グループがいっぱいであるため、データベース 'DatabaseName' のオブジェクト 'TableName' の領域を割り当てませんでした。

注:

TableName は、テーブルの名前を表します。 DatabaseName は、テーブルを含むデータベースの名前を表します。

原因

この問題は、SQL Serverが次の条件に該当する場合にヒープ テーブルが使用するすべてのページのみを解放するため発生します。

  • このテーブルの削除が発生します。
  • テーブル レベルのロックが保持されています。

注:

ヒープ テーブルは、クラスター化インデックスに関連付けられていない任意のテーブルです。

ページの割り当てが解除されていない場合、データベース内の他のオブジェクトはページを再利用できません。

ただし、SQL Server データベースで行versioning-based分離レベルを有効にすると、テーブル レベルのロックが保持されていてもページを解放できません。 行versioning-based分離レベルの詳細については、「SQL Server データベース エンジンの分離レベル」を参照してください。

回避策

この問題を回避するには、次のいずれかの方法を使用します。

  • 行のバージョン管理ベースの分離レベルが有効になっていない場合は、DELETE ステートメントに TABLOCK ヒントを含めます。 たとえば、次のようなステートメントを使用します。

    DELETE FROM <TableName> WITH (TABLOCK)
    

    注:

    <TableName> は、テーブルの名前を表します。

  • テーブル内のすべてのレコードを削除する場合は、TRUNCATE TABLE ステートメントを使用します。 たとえば、次のようなステートメントを使用します。

    TRUNCATE TABLE <TableName>
    
  • テーブルの列にクラスター化インデックスを作成します。 テーブルにクラスター化インデックスを作成する方法の詳細については、「クラスター化インデックスの 作成」を参照してください。