誰かが私に次の2つのステートメントを使用することの長所と短所の簡単な概要を教えてもらえますか?
TRUNCATE TABLE dbo.MyTable
対
DELETE FROM dbo.MyTable
すべてが言われ、行われたとき、彼らは両方とも同じことをするようです。しかし、2つの間に違いがなければなりません。
TRUNCATE
はロールバックデータを生成しないため、高速になります。テーブルで使用されるデータページの割り当てを解除するだけです。
ただし、トランザクション中にこの削除を「元に戻す」機能が必要な場合は、DELETE FROM
、ロールバックする機能を提供します。
EDIT:上記はSQL Serverには正しくないことに注意してください(ただし、Oracleには適用されます)。 SQL Serverでは、トランザクション内にいて、トランザクションがコミットされていない場合、切り捨て操作をロールバックできます。 SQL Serverの観点から見ると、DELETE FROMとTRUNCATEの重要な違いの1つは this : "DELETEステートメントは、一度に1行ずつ削除し、削除された各行のトランザクションログにエントリを記録します。テーブルデータの格納に使用されるデータページの割り当てを解除してデータを割り当て、トランザクションログにページの割り当て解除のみを記録します。
つまり、ページの割り当て解除のみがトランザクションログに記録されるため、TRUNCATE中のロギングは少なくなりますが、DELETE FROMでは各行の削除が記録されます。それがTRUNCATEが非常に速い理由の1つです。
また、そのMSDNリンクから、外部キー制約によって参照されているテーブル、インデックス付きビューに参加しているテーブル、またはトランザクションレプリケーションまたはマージレプリケーションを使用して公開されているテーブルを切り捨てることができないことに注意してください。
EDIT 2:もう1つの重要な点は、TRUNCATE TABLEがIDを初期シードにリセットするのに対し、DELETE FROMは中断したところから増分を続けることです。参照:ベンロビンソンの答え。
他の回答で言及されていないもう1つの重要な点は、TRUNCATE TABLE
will reset your 初期シードと同一、一方DELETE FROM
は、中断したところからインクリメントを続けます。
セキュリティの観点からのもう1つの違いは、TRUNCATEにはテーブルに対するALTER権限が必要ですが、DELETEにはそのテーブルに対する(ドラムロール)DELETEパーミッションが必要なだけであるということです。
TRUNCATE TABLE
はトランザクションを記録しません。これは、大きなテーブルの場合に非常に高速であることを意味します。欠点は、操作を取り消せないことです。
DELETE FROM
は削除されている各行をトランザクションログに記録するため、操作に時間がかかり、トランザクションログが劇的に大きくなります。利点は、必要に応じて操作を元に戻すことができることです。
SQLサーバーでの削除と切り捨ての概要
完全な記事については、この接続の後に行ってください: SQL Serverで削除と切り捨て
/*Truncate - Syntax*/
TRUNCATE TABLE table_name
/*Delete - Syntax*/
DELETE FROM table_name
WHERE some_condition
削除と切り捨ては、操作が明示的なトランザクションで実行された場合にのみロールバックできると考えています。それ以外の場合は、削除されたデータを復元するために復元を実行する必要があります
基本的な違いは、ログの記録方法です。 DELETEとTRUNCATEは異なる方法で記録されますが、どちらもまったく同じ方法でロールバックできます。データを変更するすべての操作が記録されます。 SQL Serverには、ログに記録されない操作などはありません。
さらに、Truncate
はテーブルのdelete trigger
をトリガーしませんが、delete
ステートメントはそれぞれのテーブルのdelete trigger
をトリガーすることを考慮する別のポイント行。
非常に重要(imo)であり、他の回答で言及されていないことの1つは、TRUNCATE
がスキーマ安定性ロック_Sch-S
を必要とするのに対し、DELETE
は行ロックを使用することです。以下を検査します。
BEGIN TRANSACTION;
BEGIN TRY
-- Truncate below will take LCK_M_SCH_S lock for TABLE_A
TRUNCATE TABLE TABLE_A
-- Lets say the query below takes 5 hours to execute
INSERT INTO
TABLE_A
SELECT
*
FROM
GIANT_TABLE (NOLOCK)
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
THROW
END CATCH
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
ここで、このクエリの開始から1〜2分後に、次を実行しようとしたと仮定します。
SELECT COUNT(*) FROM TABLE_A (NOLOCK)
NOLOCK
句を使用していることに注意してください。今何が起こると思いますか?このクエリは5時間待機します。どうして? NOLOCK
句にはSch-S
ロックがTABLE_A
に必要ですが、そのTRUNCATE
句には既にSch-S
が必要です。まだトランザクションをコミットしなかったため、そのTRUNCATE
句の後でもロックはオンのままです。テーブルのSch-S
ロックは、基本的に、TABLE_A
が列の追加/削除などによって変更されているか、切り捨てられていることを意味します。以下のようなものも実行できません:
SELECT object_id('TABLE_A')
これは5時間もスタックします。ただし、そのTRUNCATE
をDELETE FROM
に置き換えると、テーブルにSch-S
ロックがなくなり、上記のクエリが停止しないことがわかります。
DELETE
とTRUNCATE
のもう1つの違いは、テーブルが破損したときの動作です。
例えば:
DELETE FROM table_name;
エラーになります:
メッセージ3314、レベル21、状態3、行1
データベース '...'でログに記録された操作を元に戻すときに、ログレコードID()でエラーが発生しました。通常、特定の障害は以前にWindowsイベントログサービスのエラーとして記録されます。バックアップからデータベースまたはファイルを復元するか、データベースを修復します。
メッセージ0、レベル20、状態0、行0
現在のコマンドで重大なエラーが発生しました。結果があれば、破棄する必要があります。
TRUNCATE
は機能しますが:
TRUNCATE TABLE table_name;
-- Command(s) completed successfully.