<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TRANSACTION | DBA von Nebenan</title>
	<atom:link href="https://dbavonnebenan.de/tag/transaction/feed/" rel="self" type="application/rss+xml" />
	<link>https://dbavonnebenan.de</link>
	<description>Sql Server, Performance &#38; PowerShell Automation</description>
	<lastBuildDate>Sun, 08 Jun 2025 10:05:44 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://dbavonnebenan.de/wp-content/uploads/2025/04/cropped-www_logo-32x32.png</url>
	<title>TRANSACTION | DBA von Nebenan</title>
	<link>https://dbavonnebenan.de</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>TRUNCATE TABLE &#8211; DDL vs DML &#8211; deep dive in operations and practical tips</title>
		<link>https://dbavonnebenan.de/sql-server-truncate-vs-delete-dml-or-ddl-en/</link>
					<comments>https://dbavonnebenan.de/sql-server-truncate-vs-delete-dml-or-ddl-en/#respond</comments>
		
		<dc:creator><![CDATA[Gabriel]]></dc:creator>
		<pubDate>Mon, 26 May 2025 13:14:32 +0000</pubDate>
				<category><![CDATA[Sql Server]]></category>
		<category><![CDATA[TSql]]></category>
		<category><![CDATA[eng]]></category>
		<category><![CDATA[PERFORMANCE]]></category>
		<category><![CDATA[ROLLBACK]]></category>
		<category><![CDATA[TABLE]]></category>
		<category><![CDATA[TRANSACTION]]></category>
		<category><![CDATA[TRUNCATE]]></category>
		<guid isPermaLink="false">https://dbavonnebenan.de/?p=323</guid>

					<description><![CDATA[<p>Recently, I stumbled across a LinkedIn post about truncate vs. delete, just like many others out there. Typically, random members post simple SQL Server tips, nicely packaged in graphics and kept general. Although for beginners this is absolutely legitimate &#8211; since these simple entry points can help many newcomers understand and provide a great starting [&#8230;]</p>
<p>The post <a href="https://dbavonnebenan.de/sql-server-truncate-vs-delete-dml-or-ddl-en/">TRUNCATE TABLE – DDL vs DML – deep dive in operations and practical tips</a> first appeared on <a href="https://dbavonnebenan.de">DBA von Nebenan</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Recently, I stumbled across a LinkedIn post about truncate vs. delete, just like many others out there. Typically, random members post simple SQL Server tips, nicely packaged in graphics and kept general. Although for beginners this is absolutely legitimate &#8211; since<strong> </strong>these simple entry points can help many newcomers understand and provide a great starting point &#8211; nevertheless, the fact that the same topics then go viral across various accounts is clearly another matter entirely.</p>



<p>Anyway. If you&#8217;re a bit further along in the topic and already know that the pronunciation isn&#8217;t &#8222;SQL&#8220; but &#8222;sequel&#8220; <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f60a.png" alt="😊" class="wp-smiley" style="height: 1em; max-height: 1em;" />, you should fundamentally question these posts, as they mostly generalize.</p>



<p>This was also the case in a post about the top 3 SQL mistakes that &#8222;everyone&#8220; makes. And here we are, getting to the point.</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-image aligncenter size-full"><a href="https://www.linkedin.com/posts/samiul-fahim_sql-dataengineering-techtips-activity-7328642722653786112-OBfj?utm_source=share&amp;utm_medium=member_desktop&amp;rcm=ACoAACt1yIMBIZu3k0gdHLx7c_luIAnHYYBMtuc"><img fetchpriority="high" decoding="async" width="391" height="158" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/2025-05-26_09-15.png" alt="TRUNCATE cant rolled back" class="wp-image-324" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/2025-05-26_09-15.png 391w, https://dbavonnebenan.de/wp-content/uploads/2025/05/2025-05-26_09-15-300x121.png 300w" sizes="(max-width: 391px) 100vw, 391px" /></a></figure>



<p class="has-text-align-center"><a href="https://www.linkedin.com/posts/samiul-fahim_sql-dataengineering-techtips-activity-7328642722653786112-OBfj?utm_source=share&amp;utm_medium=member_desktop&amp;rcm=ACoAACt1yIMBIZu3k0gdHLx7c_luIAnHYYBMtuc" target="_blank" rel="noreferrer noopener">LinkedIn</a></p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<p>The same happened with <a href="https://www.linkedin.com/in/vedrankesegic/">Vedran Kesegic</a>, who gave the hint that TRUNCATE is apparently rollback-capable when encapsulated in a transaction. Then <a href="https://www.linkedin.com/in/saastamoinen/">Carsten Saastamoinen-Jakobsen</a> jumped in and things got wild. So wild that the whole topic hooked me so much that I did a deep dive into it. Furthermore, so much knowledge dropped in this exchange that it would be a shame if it disappeared in a comment section.</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">What to expect here</h2>



<p>I compared the exchange and looked at the core statements. I also texted separately with both of them a bit more, and Carsten gave me excerpts from one of his publications where the topic is covered technically.</p>



<p>Technically speaking, both agree, even if they don&#8217;t say it <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f923.png" alt="🤣" class="wp-smiley" style="height: 1em; max-height: 1em;" />. But what was really wild in the end was the question:</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="595" height="159" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/ddl_dml.png" alt="DML or DDL ??" class="wp-image-326" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/ddl_dml.png 595w, https://dbavonnebenan.de/wp-content/uploads/2025/05/ddl_dml-300x80.png 300w" sizes="(max-width: 595px) 100vw, 595px" /></figure>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:100%">
<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-full"><img decoding="async" width="246" height="470" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_standing_1.png" alt="" class="wp-image-330" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_standing_1.png 246w, https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_standing_1-157x300.png 157w" sizes="(max-width: 246px) 100vw, 246px" /></figure>



<p>I can say it upfront. This question is an philosophical one. I was able to form an opinion based on my research, more on that later, but basically it&#8217;s up to everyone to decide for themselves.</p>
</div>
</div>
</div>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">The Discussion &#8211; DML or DDL ?</h2>



<h3 class="wp-block-heading">Vedran Kesegic</h3>



<p><strong>Core Position: TRUNCATE is DDL</strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;TRUNCATE modifies internal system tables sys.sysallocunits and sys.sysrowsets. DELETE modifies indexes and stats&#8220;</p>
</blockquote>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;DML writes data (rows in user tables), while DDL writes metadata (rows in system tables, data that describes other/user objects). Truncate happens to write metadata (system tables) and thus is classified as DDL.&#8220;</p>
</blockquote>



<p><strong>Technical Arguments</strong></p>



<ul class="wp-block-list">
<li>Uses SCH-M (Schema Modification) lock</li>



<li>Modifies system metadata tables</li>



<li>Microsoft documentation classifies it as DDL</li>



<li>Logs page deallocations, not row deletions</li>
</ul>



<p><strong>Key Statement</strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;TRUNCATE modifies internal system tables sys.sysallocunits and sys.sysrowsets. DELETE modifies indexes and stats &#8211; see attached&#8220;</p>
</blockquote>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Carsten Saastamoinen-Jakobsen</h3>



<p><strong>Core Position: TRUNCATE is DML</strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;It is not an argument to call TRUNCATE a DDL statement because a certain lock is used! When statements are categorized, it must be based on what happens and not how a given database system solves the task.&#8220;</p>
</blockquote>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;We may have to recognize that a previous error categorization should not continue to call TRUNCATE a DDL, but recognize that it is a DML.&#8220;</p>
</blockquote>



<p><strong>Logical Arguments</strong></p>



<ul class="wp-block-list">
<li>Data is deleted, structure is preserved</li>



<li>No table definition changes occur</li>



<li>Follows semantic rules of data manipulation</li>



<li>Can delete only some partitions (not all data)</li>
</ul>



<p><strong>Key Statement</strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;I say that MS is right in the documentations because they are not telling that TRUNCATE is as DDL, because they know that TRUNCATE is a DML!&#8220;</p>



<p><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-denary-color"><em>NOTE Gabriel <br></em></mark><em>I think this is really a bit questionable because the documentation is absolutely clear</em> <em>on this point</em> &#8211;&gt; <strong><em>DDL </em></strong>(<a href="https://learn.microsoft.com/en-us/sql/t-sql/statements/statements?view=sql-server-ver17#data-definition-language" target="_blank" rel="noreferrer noopener">microsoft.com</a>)<br></p>
</blockquote>



<p><strong>Quote from publication</strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;As of version 2016, it is possible to delete only some of the data in a table with TRUNCATE, so it is even more cor­rect to call it manipulation than definition, because it is changing some of the data but not changing the structure.&#8220;</p>
</blockquote>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Points of Agreement</h3>



<ul class="wp-block-list">
<li>TRUNCATE can be rolled back in a transaction
<ul class="wp-block-list">
<li>general demo at <a href="https://blog.sqlauthority.com/2010/03/04/sql-server-rollback-truncate-command-in-transaction/" target="_blank" rel="noreferrer noopener">sqlauthority.com</a></li>



<li>deep dive demo <a href="https://www.sqlshack.com/the-internals-of-sql-truncate-and-sql-delete-statements/" target="_blank" rel="noreferrer noopener">sqlshack.com</a></li>
</ul>
</li>



<li>TRUNCATE is a logged operation</li>



<li>TRUNCATE is faster than DELETE for large datasets</li>



<li>Both understand the technical implementation</li>
</ul>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Core Disagreement</h3>



<ul class="wp-block-list">
<li><strong>Classification criteria</strong>
<ul class="wp-block-list">
<li>Implementation details</li>
</ul>
</li>



<li><strong>Authority</strong>
<ul class="wp-block-list">
<li>Vendor documentation (Vedran) vs. Logical reasoning (Carsten)</li>
</ul>
</li>



<li><strong>Perspective</strong>
<ul class="wp-block-list">
<li>How it works internally (Vedran) vs. What it does functionally (Carsten)</li>
</ul>
</li>
</ul>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">My 50 Cent</h3>



<p>So as you can see, technically it fits, but how do you view the whole thing? Maybe it&#8217;s good that I&#8217;m not preloaded with as much knowledge as both of them because from my perspective it&#8217;s quite clear: <strong>DDL!!</strong></p>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="292" height="342" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_1.png" alt="" class="wp-image-344" style="width:98px;height:auto" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_1.png 292w, https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_1-256x300.png 256w" sizes="auto, (max-width: 292px) 100vw, 292px" /></figure>



<p>Contrary to Carsten&#8217;s statement that no system tables are changed, Vedran&#8217;s statement is absolutely correct. See why&#8230; </p>
</div>



<p>&#8230; and of course because MS says it&#8217;s DDL <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f60a.png" alt="😊" class="wp-smiley" style="height: 1em; max-height: 1em;" /> ( <a href="https://learn.microsoft.com/en-us/sql/t-sql/statements/statements?view=sql-server-ver17#data-definition-language" target="_blank" rel="noreferrer noopener">microsoft.com</a> )</p>



<p>And partitioning is DML… I don&#8217;t know, here too it&#8217;s at least system columns that define the partitioning.</p>



<p></p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">How TRUNCATE works</h2>



<p>I&#8217;d like to say I&#8217;ll describe it simply, but that&#8217;s just my normal description. The topic is really complex <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/270c.png" alt="✌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">1 &#8211; TRUNCATE Command Initiated</h3>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
TRUNCATE TABLE dbo.MyTable;
</pre></div>


<ul class="wp-block-list">
<li><strong>First action</strong>: Acquire <strong>SCH-M (Schema Modification)</strong> lock on entire table</li>



<li><strong>Effect</strong>: Table is completely locked &#8211; no reads, no writes, nothing</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">2 &#8211; Identify Extents</h3>



<ul class="wp-block-list">
<li>DEEP DIVE Extents &#8211;&gt; <a href="https://learn.microsoft.com/en-us/sql/relational-databases/pages-and-extents-architecture-guide?view=sql-server-ver17" target="_blank" rel="noreferrer noopener">microsoft.com</a></li>



<li>SQL Server reads IAM pages</li>



<li>Lists all extents belonging to the table</li>



<li><strong>Still holding</strong>: SCH-M lock on table</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">3-  Lock Individual Extents</h3>



<ul class="wp-block-list">
<li>Places <strong>X (Exclusive)</strong> locks on each extent</li>



<li>These are regular data locks, NOT schema locks</li>



<li><strong>Now holding</strong>:
<ul class="wp-block-list">
<li>SCH-M lock on table (prevents access)</li>



<li>X locks on extents (marks them for deallocation)</li>
</ul>
</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">4 &#8211; Log the Operation</h3>



<ul class="wp-block-list">
<li>Writes to transaction log: &#8222;Deallocate extents 8:8, 8:16, etc.&#8220;</li>



<li><strong>Still holding</strong>: Both lock types</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">5a &#8211; If COMMIT</h3>



<ul class="wp-block-list">
<li>Updates IAM &#8211; marks extents as free</li>



<li><strong>Releases</strong> all X locks on extents</li>



<li><strong>Releases</strong> SCH-M lock on table</li>



<li>Table is accessible again</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">5b &#8211; If ROLLBACK</h3>



<ul class="wp-block-list">
<li>Discards deallocation markers</li>



<li><strong>Releases</strong> all X locks on extents</li>



<li><strong>Releases</strong> SCH-M lock on table</li>



<li>Everything unchanged</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Why Two Different Lock Types?</h3>



<p><strong>SCH-M Lock:</strong></p>



<ul class="wp-block-list">
<li>&#8222;Nobody touch this table AT ALL&#8220;</li>



<li>Typical for DDL operations</li>



<li>Prevents even metadata queries</li>
</ul>



<p><strong>X Locks on Extents:</strong></p>



<ul class="wp-block-list">
<li>&#8222;These specific data blocks are being modified&#8220;</li>



<li>Typical for data operations</li>



<li>Ensures extents aren&#8217;t reused until commit/rollback by other sessions</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">My humble Opinion</h3>



<p>Given this knowledge, the case is actually clear for me, but how do you see it? Indeed, here no user data is being manipulated; instead, system-level assignments are being adjusted. Consequently, I&#8217;ll allow myself, despite my new half-knowledge, to make the following comparison:</p>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="307" height="328" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_2.png" alt="" class="wp-image-345" style="width:131px;height:auto" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_2.png 307w, https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_2-281x300.png 281w" sizes="auto, (max-width: 307px) 100vw, 307px" /></figure>



<p>&#8222;I also don&#8217;t say I&#8217;m deleting text in a Word document when I quick format the disk and only delete the block allocation.&#8220;</p>
</div>



<p><br>Yes, I think that&#8217;s a nice comparison&#8230; Case closed, now a few technically interesting aspects and solutions</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Technical Part, Hacks and How2</h2>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="643" height="388" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/meme_trunc.jpg" alt="" class="wp-image-348" style="width:325px;height:auto" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/meme_trunc.jpg 643w, https://dbavonnebenan.de/wp-content/uploads/2025/05/meme_trunc-300x181.jpg 300w" sizes="auto, (max-width: 643px) 100vw, 643px" /></figure>



<p class="has-text-align-center has-medium-font-size">&#8230; practical, not technical <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">TRUNCATE with Survivor Table (Temporary Table)</h3>



<p>Data that is still required is simply moved to a temporary table and retrieved after TRUNCATE</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
-- Step 1: Create temp table with rows to keep
	SELECT * INTO #SurvivorRows 
	FROM 
		MyTable 
	WHERE
		DateColumn &gt;= &#039;2024-01-01&#039;

-- Step 2: Truncate the entire table
	TRUNCATE TABLE MyTable

-- Step 3: Re-insert survivor rows
	INSERT INTO MyTable
	SELECT * FROM #SurvivorRows

-- Step 4: Clean up
	DROP TABLE #SurvivorRows
</pre></div>


<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">TRUNCATE with PARTITION option (2016++)</h3>



<p>Since SQL Server 2016 (every edition) it is possible to specify partitions or ranges of partitions</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
-- Truncate specific partitions
	TRUNCATE TABLE MyPartitionedTable 
	     WITH (PARTITIONS (2, 4 TO 6))

-- Check partition status
	SELECT 
		 partition_number
		,rows 
	FROM
		sys.partitions 
	WHERE 
		OBJECT_NAME(OBJECT_ID) = &#039;MyPartitionedTable&#039;
</pre></div>


<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">TRUNCATE is always a transaction&#8230;</h3>



<p>&#8230;. and must be considered during RESTORING. Carsten illustrated this whole thing very nicely in his publication. I&#8217;m just describing it, that has to suffice at this point <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f61d.png" alt="😝" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>Even though we only write <strong>TRUNCATE TABLE</strong>, SQL Server still uses <strong>BEGIN</strong> and <strong>COMMIT TRANSACTION</strong>, which of course is recorded in the TLog. Accordingly, during a POINT IN TIME RECOVERY, the data in the table remains available until the TLog with the corresponding TRANSACTION is restored, or the time of the TRUNCATE transaction has been exceeded.</p>



<p>So you can also restore the data <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f44c.png" alt="👌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Continuously read Transaction log file data with fn_dblog and fn_dump_dblog</h3>



<p>Vedran wrote in one of his posts that there&#8217;s an undocumented function where you can read log records at runtime. There&#8217;s also a very cool article about this on sqlshack.com</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="has-text-align-center"><em><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-septenary-color">NOT recommended for production but only for test / education.</mark></em></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>


https://www.sqlshack.com/how-to-continuously-read-transaction-log-file-data-directly-in-a-sql-server-database-with-fn_dblog-and-fn_dump_dblog/


<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Finally</h2>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="284" height="334" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_3.png" alt="" class="wp-image-355" style="width:124px;height:auto" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_3.png 284w, https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_3-255x300.png 255w" sizes="auto, (max-width: 284px) 100vw, 284px" /></figure>



<p>Let&#8217;s get to my initially mentioned point that all these SQL Server tips from randoms should be questioned. Because the statement that <strong>truncate is not rollback safe</strong> is simply wrong. The path to this realization was long for me, initiated by the conversation between Vedran and Carsten. I really learned a lot left and right, which I also wanted to record here again for posterity.</p>
</div>



<p>In the end, it doesn&#8217;t matter whether it&#8217;s <strong>DDL</strong> or <strong>DML</strong>. In the general SQL Server standard, for example, it&#8217;s described as DML, most RDBMSs in dialect with DDL. We&#8217;ll just agree on <strong>DDL</strong> and that&#8217;s it. Much more exciting is what happens under the hood.</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>Best comment from Vedran <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f923.png" alt="🤣" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-overpass-mono-font-family">&#8222;Or you are trying to argue with SQL Certified Master about SQL? Good luck Mr :)&#8220;</p>
</blockquote>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Links from the text</h2>


https://learn.microsoft.com/en-us/sql/t-sql/statements/statements?view=sql-server-ver17#data-definition-language

https://learn.microsoft.com/en-us/sql/t-sql/statements/truncate-table-transact-sql?view=sql-server-ver17

https://blog.sqlauthority.com/2010/03/04/sql-server-rollback-truncate-command-in-transaction/

https://www.sqlshack.com/the-internals-of-sql-truncate-and-sql-delete-statements/

https://www.sqlshack.com/how-to-continuously-read-transaction-log-file-data-directly-in-a-sql-server-database-with-fn_dblog-and-fn_dump_dblog/

https://en.wikipedia.org/wiki/Truncate_(SQL)

https://learn.microsoft.com/en-us/sql/relational-databases/pages-and-extents-architecture-guide?view=sql-server-ver17


<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Full Conversation</h2>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>Expand</summary>
<p><strong>Vedran Kesegic</strong></p>



<p>In sql server, truncate can be rolled back (if encapsulated within transaction). It is a logged operation.</p>



<p><strong>Carsten Saastamoinen-Jakobsen</strong></p>



<p>With DELETE we can specify the WHERE clause and some or all rows can be removed. All deleted rows are logged with BEFORE IMAGE/the data values. With TRUNCATE we can delete all rows or only the rows in one or more partitions, if we have a partition table. The only information logged is the pageid. The physical removing/releasing to unused pages happens in a background task after COMMIT. No data is stored in the log, so less and faster! And it is not possible to restore to point in time because no data is logged. The pageid in the log can already have being &#8218;released&#8216; to unused pages and therefore already used to data from another object &#8211; table/index. Before COMMIT the pages is still allocated to the table and still with data. If no explicit transaction is specified the transaction is already committed!</p>



<p><strong>Vedran Kesegic</strong></p>



<p>&#8222;No data is stored in the log&#8220; and &#8222;not possible to restore to point in time&#8220; is both incorrect for TRUNCATE. The difference is, truncate logs only deallocation of pages, which is multiple orders of magnitude less (basically insignifficant) compared to DELETE which logs data that is deleted. That is why truncate is &#8222;instant&#8220;. If you delete eg. 10GB of data, you wait for 10GB to be written to transaction log, which takes time. Truncate logs maybe 1KB for deallocation info, which is instant. If you do not want to delete all rows, you can still use TRUNCATE by storing survivor rows aside before truncating, and inserting them back after truncate. Even better, you can use SWITCH into some dummy table (even with not-partitioned tables) to remove rows quickly, and then insert survivor rows back from that dummy into original table. That is the fastest way to delete when a smaller percent of rows needs to survive.</p>



<p><strong>Vedran Kesegic</strong></p>



<p>Obvious difference is that truncate removes all rows from table (&#8222;truncate table&#8220;) or from partition(s), when using &#8222;trancate table xy with partitions (&#8230;)&#8220;. You cannot choose which rows to delete, they all are gone. With delete you can have a WHERE clause to choose which rows to delete. Delete is more appropriate if you need to delete a small percentage of table rows (or partition rows).</p>



<p><strong>Vedran Kesegic</strong></p>



<p>Truncate is a metadata operation, requires a different lock (SCH_M, schema modification lock). If also has some restrictins regarding foreign keys etc. Check the documentation for the list of limitations: https://learn.microsoft.com/en-us/sql/t-sql/statements/truncate-table-transact-sql</p>



<p><strong>Carsten Saastamoinen-Jakobsen</strong></p>



<p>It is not an argument to call TRUNCATE a DDL statement because a certain lock is used! When statements are categorized, it must be based on what happens and not how a given database system solves the task. Data is deleted, the structure is preserved and only some data may be deleted. When one or more partitions are deleted, the condition is also well-known, but just limited. In previous versions of database systems &#8211; and perhaps still &#8211; a TRUNCATE was performed by a DROP TABLE + CREATE TABLE. Hence DDL rights. It just shows that it is problematic to categorize based on how it is performed and not based on what actually happens. If we look at the documentation for SQL Server, it is not mentioned that TRUNCATE is a DDL. We may have to recognize that a previous error categorization should not continue to call TRUNCATE a DDL, but recognize that it is a DML. We will also be free from erroneous claims about only deleting all rows, that space is not released, that the transaction cannot be rolled back, &#8230;. A DELETE operation without a user-defined transaction cannot be rolled back either! But DELETE is DML and not DDL. TRUNCATE is &#8218;created&#8216; for having af fast way of deleting rows, and extended for only deleting some of the rows &#8211; DML!!!</p>



<p><strong>Vedran Kesegic</strong></p>



<p>No, the SCH-M lock (the &#8222;king of all locks&#8220;) is not the sole reason why TRUNCATE is DDL. DML writes data (rows in user tables), while DDL writes metadata (rows in system tables, data that describes other/user objects). Truncate happens to write metadata (system tables) and thus is classified as DDL. See the doc: https://learn.microsoft.com/en-us/previous-versions/sql/sql-server-2012/ff848799(v=sql.110)</p>



<p><strong>Carsten Saastamoinen-Jakobsen</strong></p>



<p>Can you tell which data is written to the system tables that is not written when removing rows by DELETE? The only additional information is, that with TRUNCATE of all rows without specifying partitions is, that the &#8218;identity&#8216; is reset to the initial values. Removing some or all rows with specifying partitions, this value is not reset to the initial value. Empty page are handled in the same way as empty page after DELETE! All indexes are preserved, the table definition is NOT changed, &#8230;.</p>



<p><strong>Vedran Kesegic</strong></p>



<p>Better than that &#8211; you can see for yourself! The exact difference and details are present in transaction log records after you do TRUNCATE and compare that to log records that DELETE generates. Use fn_dblog() function, but only on the test system because it is undocumented and might have an impact.</p>



<p>Or you are trying to say that Microsoft is wrong in documentation? If so, report it to MS so doc can be fixed. But in this case there is nothing to fix.</p>



<p>Or you are trying to argue with SQL Certified Master about SQL? Good luck Mr <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p><strong>Carsten Saastamoinen-Jakobsen</strong></p>



<p>I say that MS is right in the documentations because they are not telling that TRUNCATE is as DDL, because they know that TRUNCATE is a DML!. Of course there is less in the log &#8211; it is the idea wit TRUNCATE!!!!!!!! Just te functionality and te reason for implementing TRUNCATE as an alternative to DELETE. But the log is NOT the system tables!!!!! So please tell which system tables are updated as they are updated when CRAETE, ALTER and DROP but NOT updated when INSERT, DELETE or UPDATE.</p>



<p><strong>Vedran Kesegic</strong></p>



<p>TRUNCATE modifies internal system tables sys.sysallocunits and sys.sysrowsets. DELETE modifies indexes and stats &#8211; see attached pictures. You could do that yourself using fn_dblog as instructed, but I did that for you so you don&#8217;t have to. If you want to know more about deep SQL Server internals you can attend one of my trainings, or trainings of other SQL Masters like Brent Ozar, Paul Randal (sqlskills), etc.</p>



<p><strong>Carsten Saastamoinen-Jakobsen</strong></p>



<p>Of course they are modified as INSERT DELETE and UPDATE modify this informations. But INSERT, DELETE and UPDATE are still only DML and not DDL. And I am not impressed of your job by showing me this information. If you was showing the same for the other DML statements it would be fine. So maybe you should modify your course material and also shows the same for the other DML statements!!!!</p>
</details>



<p></p><p>The post <a href="https://dbavonnebenan.de/sql-server-truncate-vs-delete-dml-or-ddl-en/">TRUNCATE TABLE – DDL vs DML – deep dive in operations and practical tips</a> first appeared on <a href="https://dbavonnebenan.de">DBA von Nebenan</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://dbavonnebenan.de/sql-server-truncate-vs-delete-dml-or-ddl-en/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>TRUNCATE TABLE Operationen im Detail &#8211; ROLLBACK ist doch möglich</title>
		<link>https://dbavonnebenan.de/sql-server-truncate-vs-delete-dml-or-ddl-de/</link>
					<comments>https://dbavonnebenan.de/sql-server-truncate-vs-delete-dml-or-ddl-de/#respond</comments>
		
		<dc:creator><![CDATA[Gabriel]]></dc:creator>
		<pubDate>Mon, 26 May 2025 08:16:15 +0000</pubDate>
				<category><![CDATA[Sql Server]]></category>
		<category><![CDATA[TSql]]></category>
		<category><![CDATA[DE]]></category>
		<category><![CDATA[PERFORMANCE]]></category>
		<category><![CDATA[ROLLBACK]]></category>
		<category><![CDATA[TABLE]]></category>
		<category><![CDATA[TRANSACTION]]></category>
		<category><![CDATA[TRUNCATE]]></category>
		<guid isPermaLink="false">https://dbavonnebenan.de/?p=428</guid>

					<description><![CDATA[<p>Kürzlich bin ich über einen LinkedIn-Post zu TRUNCATE vs. DELETE gestolpert, wie so viele andere auch. Typischerweise posten zufällige Mitglieder einfache SQL Server Tipps, schön verpackt in Grafiken und allgemein gehalten. Obwohl das für Anfänger absolut legitim ist &#8211; da diese einfachen Einstiegspunkte vielen Neulingen helfen können zu verstehen und einen großartigen Startpunkt bieten &#8211; [&#8230;]</p>
<p>The post <a href="https://dbavonnebenan.de/sql-server-truncate-vs-delete-dml-or-ddl-de/">TRUNCATE TABLE Operationen im Detail – ROLLBACK ist doch möglich</a> first appeared on <a href="https://dbavonnebenan.de">DBA von Nebenan</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Kürzlich bin ich über einen LinkedIn-Post zu TRUNCATE vs. DELETE gestolpert, wie so viele andere auch. Typischerweise posten zufällige Mitglieder einfache SQL Server Tipps, schön verpackt in Grafiken und allgemein gehalten. Obwohl das für Anfänger absolut legitim ist &#8211; da<strong> </strong>diese einfachen Einstiegspunkte vielen Neulingen helfen können zu verstehen und einen großartigen Startpunkt bieten &#8211; ist die Tatsache, dass dieselben Themen dann viral über verschiedene Accounts gehen, klar eine ganz andere Sache.</p>



<p>Wie auch immer. Wenn du beim Thema schon etwas weiter bist und bereits weißt, dass die Aussprache nicht &#8222;SQL&#8220; sondern &#8222;Sequel&#8220; ist <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f60a.png" alt="😊" class="wp-smiley" style="height: 1em; max-height: 1em;" />, solltest du diese Posts grundsätzlich hinterfragen, da sie meist verallgemeinern.</p>



<p>So war es auch bei einem Post über die Top 3 SQL-Fehler, die &#8222;jeder&#8220; macht. Und hier kommen wir zum Punkt &#8211; TRUNCATE TABLE und seine Besonderheiten.</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-image aligncenter size-full"><a href="https://www.linkedin.com/posts/samiul-fahim_sql-dataengineering-techtips-activity-7328642722653786112-OBfj?utm_source=share&amp;utm_medium=member_desktop&amp;rcm=ACoAACt1yIMBIZu3k0gdHLx7c_luIAnHYYBMtuc"><img loading="lazy" decoding="async" width="391" height="158" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/2025-05-26_09-15.png" alt="TRUNCATE kann nicht zurückgerollt werden" class="wp-image-324" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/2025-05-26_09-15.png 391w, https://dbavonnebenan.de/wp-content/uploads/2025/05/2025-05-26_09-15-300x121.png 300w" sizes="auto, (max-width: 391px) 100vw, 391px" /></a></figure>



<p class="has-text-align-center"><a href="https://www.linkedin.com/posts/samiul-fahim_sql-dataengineering-techtips-activity-7328642722653786112-OBfj?utm_source=share&amp;utm_medium=member_desktop&amp;rcm=ACoAACt1yIMBIZu3k0gdHLx7c_luIAnHYYBMtuc" target="_blank" rel="noreferrer noopener">LinkedIn</a></p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Dasselbe passierte mit <a href="https://www.linkedin.com/in/vedrankesegic/">Vedran Kesegic</a>, der den Hinweis gab, dass TRUNCATE TABLE anscheinend rollback-fähig ist, wenn es in einer Transaktion gekapselt wird. Dann sprang <a href="https://www.linkedin.com/in/saastamoinen/">Carsten Saastamoinen-Jakobsen</a> ein und die Sache wurde wild. So wild, dass mich das ganze Thema dermaßen gepackt hat, dass ich einen Deep Dive gemacht habe. Außerdem fiel in diesem Austausch so viel Wissen ab, dass es schade wäre, wenn es in einem Kommentarbereich verschwindet.</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Was dich hier erwartet &#8211; TRUNCATE TABLE im Detail</h2>



<p>Ich habe den Austausch verglichen und mir die Kernaussagen angeschaut. Ich habe auch separat mit beiden etwas mehr getextet, und Carsten gab mir Auszüge aus einer seiner Publikationen, wo das Thema technisch behandelt wird.</p>



<p>Technisch gesehen sind sich beide einig, auch wenn sie es nicht sagen <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f923.png" alt="🤣" class="wp-smiley" style="height: 1em; max-height: 1em;" />. Aber was am Ende wirklich wild war, war die Frage zum TRUNCATE TABLE Befehl:</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="595" height="159" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/ddl_dml.png" alt="DML oder DDL - TRUNCATE TABLE Klassifizierung" class="wp-image-326" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/ddl_dml.png 595w, https://dbavonnebenan.de/wp-content/uploads/2025/05/ddl_dml-300x80.png 300w" sizes="auto, (max-width: 595px) 100vw, 595px" /></figure>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:100%">
<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="246" height="470" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_standing_1.png" alt="" class="wp-image-330" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_standing_1.png 246w, https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_standing_1-157x300.png 157w" sizes="auto, (max-width: 246px) 100vw, 246px" /></figure>



<p>Ich kann es vorwegnehmen. Diese Frage zur TRUNCATE TABLE Klassifizierung ist eine philosophische. Ich konnte mir basierend auf meiner Recherche eine Meinung bilden, mehr dazu später, aber grundsätzlich liegt es an jedem selbst zu entscheiden.</p>
</div>
</div>
</div>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Die Diskussion &#8211; TRUNCATE TABLE als DML oder DDL?</h2>



<h3 class="wp-block-heading">Vedran Kesegic</h3>



<p><strong>Kernposition: TRUNCATE TABLE ist DDL</strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;TRUNCATE modifies internal system tables sys.sysallocunits and sys.sysrowsets. DELETE modifies indexes and stats&#8220;</p>
</blockquote>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;DML writes data (rows in user tables), while DDL writes metadata (rows in system tables, data that describes other/user objects). Truncate happens to write metadata (system tables) and thus is classified as DDL.&#8220;</p>
</blockquote>



<p><strong>Technische Argumente für TRUNCATE TABLE als DDL</strong></p>



<ul class="wp-block-list">
<li>Verwendet SCH-M (Schema Modification) Lock</li>



<li>Modifiziert System-Metadaten-Tabellen</li>



<li>Microsoft-Dokumentation klassifiziert es als DDL</li>



<li>Loggt Page-Deallocations, nicht Row-Deletions</li>
</ul>



<p><strong>Kernaussage zum TRUNCATE TABLE Befehl</strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;TRUNCATE modifies internal system tables sys.sysallocunits and sys.sysrowsets. DELETE modifies indexes and stats &#8211; see attached&#8220;</p>
</blockquote>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Carsten Saastamoinen-Jakobsen</h3>



<p><strong>Kernposition: TRUNCATE TABLE ist DML</strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;It is not an argument to call TRUNCATE a DDL statement because a certain lock is used! When statements are categorized, it must be based on what happens and not how a given database system solves the task.&#8220;</p>
</blockquote>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;We may have to recognize that a previous error categorization should not continue to call TRUNCATE a DDL, but recognize that it is a DML.&#8220;</p>
</blockquote>



<p><strong>Logische Argumente für TRUNCATE TABLE als DML</strong></p>



<ul class="wp-block-list">
<li>Daten werden gelöscht, Struktur bleibt erhalten</li>



<li>Keine Änderungen an der Tabellendefinition</li>



<li>Folgt semantischen Regeln der Datenmanipulation</li>



<li>Kann nur bestimmte Partitionen löschen (nicht alle Daten)</li>
</ul>



<p><strong>Kernaussage zur TRUNCATE TABLE Klassifizierung</strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;I say that MS is right in the documentations because they are not telling that TRUNCATE is as DDL, because they know that TRUNCATE is a DML!&#8220;</p>



<p><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-denary-color"><em>ANMERKUNG Gabriel <br></em></mark><em>Ich denke, das ist wirklich etwas fragwürdig, weil die Dokumentation absolut klar</em> <em>zu diesem Punkt ist</em> &#8211;&gt; <strong><em>DDL </em></strong>(<a href="https://learn.microsoft.com/en-us/sql/t-sql/statements/statements?view=sql-server-ver17#data-definition-language" target="_blank" rel="noreferrer noopener">microsoft.com</a>)<br></p>
</blockquote>



<p><strong>Zitat aus der Publikation zum TRUNCATE TABLE</strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8222;As of version 2016, it is possible to delete only some of the data in a table with TRUNCATE, so it is even more cor­rect to call it manipulation than definition, because it is changing some of the data but not changing the structure.&#8220;</p>
</blockquote>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Einigungspunkte bei TRUNCATE TABLE</h3>



<ul class="wp-block-list">
<li>TRUNCATE TABLE kann in einer Transaktion zurückgerollt werden
<ul class="wp-block-list">
<li>allgemeine Demo bei <a href="https://blog.sqlauthority.com/2010/03/04/sql-server-rollback-truncate-command-in-transaction/" target="_blank" rel="noreferrer noopener">sqlauthority.com</a></li>



<li>detaillierte Demo <a href="https://www.sqlshack.com/the-internals-of-sql-truncate-and-sql-delete-statements/" target="_blank" rel="noreferrer noopener">sqlshack.com</a></li>
</ul>
</li>



<li>TRUNCATE TABLE ist eine geloggte Operation</li>



<li>TRUNCATE TABLE ist schneller als DELETE bei großen Datensätzen</li>



<li>Beide verstehen die technische Implementierung</li>
</ul>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Hauptstreitpunkt bei TRUNCATE TABLE</h3>



<ul class="wp-block-list">
<li><strong>Klassifizierungskriterien für TRUNCATE TABLE</strong>
<ul class="wp-block-list">
<li>Implementierungsdetails</li>
</ul>
</li>



<li><strong>Autorität</strong>
<ul class="wp-block-list">
<li>Vendor-Dokumentation (Vedran) vs. Logische Begründung (Carsten)</li>
</ul>
</li>



<li><strong>Perspektive zum TRUNCATE TABLE Befehl</strong>
<ul class="wp-block-list">
<li>Wie es intern funktioniert (Vedran) vs. Was es funktional macht (Carsten)</li>
</ul>
</li>
</ul>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Meine Einschätzung zu TRUNCATE TABLE</h3>



<p>Wie du siehst, passt es technisch, aber wie betrachtest du das Ganze? Vielleicht ist es gut, dass ich nicht mit so viel Wissen vorab beladen bin wie beide, denn aus meiner Sicht ist es ziemlich klar: <strong>TRUNCATE TABLE ist DDL!!</strong></p>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="292" height="342" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_1.png" alt="" class="wp-image-344" style="width:98px;height:auto" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_1.png 292w, https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_1-256x300.png 256w" sizes="auto, (max-width: 292px) 100vw, 292px" /></figure>



<p>Entgegen Carstens Aussage, dass keine Systemtabellen geändert werden, ist Vedrans Aussage absolut korrekt. Sieh warum&#8230; </p>
</div>



<p>&#8230; und natürlich weil Microsoft sagt, dass TRUNCATE TABLE DDL ist <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f60a.png" alt="😊" class="wp-smiley" style="height: 1em; max-height: 1em;" /> ( <a href="https://learn.microsoft.com/en-us/sql/t-sql/statements/statements?view=sql-server-ver17#data-definition-language" target="_blank" rel="noreferrer noopener">microsoft.com</a> )</p>



<p>Und Partitionierung ist DML… ich weiß nicht, auch hier sind es zumindest Systemspalten, die die Partitionierung definieren.</p>



<p></p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Wie TRUNCATE TABLE funktioniert &#8211; Schritt für Schritt</h2>



<p>Ich würde gerne sagen, dass ich es einfach beschreibe, aber das ist einfach meine normale Beschreibung. Das Thema TRUNCATE TABLE ist wirklich komplex <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/270c.png" alt="✌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">1 &#8211; TRUNCATE TABLE Befehl initiiert</h3>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
TRUNCATE TABLE dbo.MyTable;
</pre></div>


<ul class="wp-block-list">
<li><strong>Erste Aktion</strong>: Akquiriert <strong>SCH-M (Schema Modification)</strong> Lock auf gesamte Tabelle</li>



<li><strong>Effekt</strong>: Tabelle ist komplett gesperrt &#8211; keine Reads, keine Writes, nichts</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">2 &#8211; Extents identifizieren bei TRUNCATE TABLE</h3>



<ul class="wp-block-list">
<li>DEEP DIVE Extents &#8211;&gt; <a href="https://learn.microsoft.com/en-us/sql/relational-databases/pages-and-extents-architecture-guide?view=sql-server-ver17" target="_blank" rel="noreferrer noopener">microsoft.com</a></li>



<li>SQL Server liest IAM-Pages</li>



<li>Listet alle Extents auf, die zur Tabelle gehören</li>



<li><strong>Hält weiterhin</strong>: SCH-M Lock auf Tabelle</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">3 &#8211; Einzelne Extents bei TRUNCATE TABLE sperren</h3>



<ul class="wp-block-list">
<li>Platziert <strong>X (Exclusive)</strong> Locks auf jeden Extent</li>



<li>Das sind reguläre Data-Locks, KEINE Schema-Locks</li>



<li><strong>Hält jetzt</strong>:
<ul class="wp-block-list">
<li>SCH-M Lock auf Tabelle (verhindert Zugriff)</li>



<li>X Locks auf Extents (markiert sie für Deallocation)</li>
</ul>
</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">4 &#8211; TRUNCATE TABLE Operation loggen</h3>



<ul class="wp-block-list">
<li>Schreibt ins Transaction-Log: &#8222;Deallocate extents 8:8, 8:16, etc.&#8220;</li>



<li><strong>Hält weiterhin</strong>: Beide Lock-Typen</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">5a &#8211; Bei COMMIT der TRUNCATE TABLE Operation</h3>



<ul class="wp-block-list">
<li>Aktualisiert IAM &#8211; markiert Extents als frei</li>



<li><strong>Gibt frei</strong> alle X Locks auf Extents</li>



<li><strong>Gibt frei</strong> SCH-M Lock auf Tabelle</li>



<li>Tabelle ist wieder zugänglich</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">5b &#8211; Bei ROLLBACK der TRUNCATE TABLE Operation</h3>



<ul class="wp-block-list">
<li>Verwirft Deallocation-Marker</li>



<li><strong>Gibt frei</strong> alle X Locks auf Extents</li>



<li><strong>Gibt frei</strong> SCH-M Lock auf Tabelle</li>



<li>Alles bleibt unverändert</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Warum zwei verschiedene Lock-Typen bei TRUNCATE TABLE?</h3>



<p><strong>SCH-M Lock:</strong></p>



<ul class="wp-block-list">
<li>&#8222;Niemand rührt diese Tabelle ÜBERHAUPT an&#8220;</li>



<li>Typisch für DDL-Operationen</li>



<li>Verhindert sogar Metadaten-Abfragen</li>
</ul>



<p><strong>X Locks auf Extents:</strong></p>



<ul class="wp-block-list">
<li>&#8222;Diese spezifischen Datenblöcke werden modifiziert&#8220;</li>



<li>Typisch für Daten-Operationen</li>



<li>Stellt sicher, dass Extents nicht von anderen Sessions wiederverwendet werden bis commit/rollback</li>
</ul>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Meine bescheidene Meinung zu TRUNCATE TABLE</h3>



<p>Mit diesem Wissen ist der Fall eigentlich klar für mich, aber wie siehst du es? Tatsächlich werden hier keine Benutzerdaten manipuliert; stattdessen werden System-Level-Zuweisungen angepasst. Folglich erlaube ich mir, trotz meines neuen Halbwissens, den folgenden Vergleich zu ziehen:</p>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="307" height="328" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_2.png" alt="" class="wp-image-345" style="width:131px;height:auto" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_2.png 307w, https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_2-281x300.png 281w" sizes="auto, (max-width: 307px) 100vw, 307px" /></figure>



<p>&#8222;Ich sage auch nicht, dass ich Text in einem Word-Dokument lösche, wenn ich die Festplatte schnell formatiere und nur die Block-Allocation lösche.&#8220;</p>
</div>



<p><br>Ja, ich denke das ist ein schöner Vergleich&#8230; Fall abgeschlossen, jetzt ein paar technisch interessante Aspekte und Lösungen zum TRUNCATE TABLE Befehl</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Technischer Teil, Hacks und TRUNCATE TABLE How-To</h2>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="643" height="388" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/meme_trunc.jpg" alt="" class="wp-image-348" style="width:325px;height:auto" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/meme_trunc.jpg 643w, https://dbavonnebenan.de/wp-content/uploads/2025/05/meme_trunc-300x181.jpg 300w" sizes="auto, (max-width: 643px) 100vw, 643px" /></figure>



<p class="has-text-align-center has-medium-font-size">&#8230; praktisch, nicht technisch <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">TRUNCATE TABLE mit Survivor Table (Temporary Table)</h3>



<p>Daten, die noch benötigt werden, werden einfach in eine temporäre Tabelle verschoben und nach TRUNCATE TABLE wieder abgerufen</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
-- Step 1: Create temp table with rows to keep
	SELECT * INTO #SurvivorRows 
	FROM 
		MyTable 
	WHERE
		DateColumn &gt;= &#039;2024-01-01&#039;

-- Step 2: Truncate the entire table
	TRUNCATE TABLE MyTable

-- Step 3: Re-insert survivor rows
	INSERT INTO MyTable
	SELECT * FROM #SurvivorRows

-- Step 4: Clean up
	DROP TABLE #SurvivorRows
</pre></div>


<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">TRUNCATE TABLE mit PARTITION Option (2016++)</h3>



<p>Seit SQL Server 2016 (jede Edition) ist es möglich, Partitionen oder Bereiche von Partitionen bei TRUNCATE TABLE zu spezifizieren</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
-- Truncate specific partitions
	TRUNCATE TABLE MyPartitionedTable 
	     WITH (PARTITIONS (2, 4 TO 6))

-- Check partition status
	SELECT 
		 partition_number
		,rows 
	FROM
		sys.partitions 
	WHERE 
		OBJECT_NAME(OBJECT_ID) = &#039;MyPartitionedTable&#039;
</pre></div>


<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">TRUNCATE TABLE ist immer eine Transaktion&#8230;</h3>



<p>&#8230;. und muss beim RESTORE berücksichtigt werden. Carsten hat das ganze sehr schön in seiner Publikation illustriert. Ich beschreibe es nur, das muss an dieser Stelle reichen <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f61d.png" alt="😝" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>Obwohl wir nur <strong>TRUNCATE TABLE</strong> schreiben, verwendet SQL Server trotzdem <strong>BEGIN</strong> und <strong>COMMIT TRANSACTION</strong>, was natürlich im TLog aufgezeichnet wird. Entsprechend bleiben bei einer POINT IN TIME RECOVERY die Daten in der Tabelle verfügbar, bis das TLog mit der entsprechenden TRANSACTION wiederhergestellt wird, oder die Zeit der TRUNCATE TABLE Transaktion überschritten wurde.</p>



<p>Du kannst also auch die Daten wiederherstellen <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f44c.png" alt="👌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Transaction Log File Daten kontinuierlich lesen mit fn_dblog und fn_dump_dblog</h3>



<p>Vedran schrieb in einem seiner Posts, dass es eine undokumentierte Funktion gibt, wo du Log-Records zur Laufzeit lesen kannst. Es gibt auch einen sehr coolen Artikel dazu auf sqlshack.com</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="has-text-align-center"><em><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-septenary-color">NICHT empfohlen für Produktion, sondern nur für Test / Bildung.</mark></em></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>


https://www.sqlshack.com/how-to-continuously-read-transaction-log-file-data-directly-in-a-sql-server-database-with-fn_dblog-and-fn_dump_dblog/


<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Fazit zu TRUNCATE TABLE</h2>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="284" height="334" src="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_3.png" alt="" class="wp-image-355" style="width:124px;height:auto" srcset="https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_3.png 284w, https://dbavonnebenan.de/wp-content/uploads/2025/05/emotes_3-255x300.png 255w" sizes="auto, (max-width: 284px) 100vw, 284px" /></figure>



<p>Kommen wir zu meinem eingangs erwähnten Punkt, dass all diese SQL Server Tipps von randoms hinterfragt werden sollten. Denn die Aussage, dass <strong>TRUNCATE TABLE nicht rollback-sicher</strong> ist, ist schlichtweg falsch. Der Weg zu dieser Erkenntnis war für mich lang, eingeleitet durch die Unterhaltung zwischen Vedran und Carsten. Ich habe wirklich viel links und rechts dazugelernt, was ich auch hier nochmal für die Nachwelt festhalten wollte.</p>
</div>



<p>Am Ende ist es egal, ob TRUNCATE TABLE <strong>DDL</strong> oder <strong>DML</strong> ist. Im allgemeinen SQL Server Standard wird es beispielsweise als DML beschrieben, die meisten RDBMSs im Dialekt mit DDL. Wir einigen uns einfach auf <strong>DDL</strong> und gut ist. Viel spannender ist, was unter der Haube beim TRUNCATE TABLE Befehl passiert.</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>Bester Kommentar von Vedran <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f923.png" alt="🤣" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-overpass-mono-font-family">&#8222;Or you are trying to argue with SQL Certified Master about SQL? Good luck Mr :)&#8220;</p>
</blockquote>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Links aus dem Text</h2>


https://learn.microsoft.com/en-us/sql/t-sql/statements/statements?view=sql-server-ver17#data-definition-language

https://learn.microsoft.com/en-us/sql/t-sql/statements/truncate-table-transact-sql?view=sql-server-ver17

https://blog.sqlauthority.com/2010/03/04/sql-server-rollback-truncate-command-in-transaction/

https://www.sqlshack.com/the-internals-of-sql-truncate-and-sql-delete-statements/

https://www.sqlshack.com/how-to-continuously-read-transaction-log-file-data-directly-in-a-sql-server-database-with-fn_dblog-and-fn_dump_dblog/

https://en.wikipedia.org/wiki/Truncate_(SQL)

https://learn.microsoft.com/en-us/sql/relational-databases/pages-and-extents-architecture-guide?view=sql-server-ver17


<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Full Conversation</h2>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>Expand</summary>
<p><strong>Vedran Kesegic</strong></p>



<p>In sql server, truncate can be rolled back (if encapsulated within transaction). It is a logged operation.</p>



<p><strong>Carsten Saastamoinen-Jakobsen</strong></p>



<p>With DELETE we can specify the WHERE clause and some or all rows can be removed. All deleted rows are logged with BEFORE IMAGE/the data values. With TRUNCATE we can delete all rows or only the rows in one or more partitions, if we have a partition table. The only information logged is the pageid. The physical removing/releasing to unused pages happens in a background task after COMMIT. No data is stored in the log, so less and faster! And it is not possible to restore to point in time because no data is logged. The pageid in the log can already have being &#8218;released&#8216; to unused pages and therefore already used to data from another object &#8211; table/index. Before COMMIT the pages is still allocated to the table and still with data. If no explicit transaction is specified the transaction is already committed!</p>



<p><strong>Vedran Kesegic</strong></p>



<p>&#8222;No data is stored in the log&#8220; and &#8222;not possible to restore to point in time&#8220; is both incorrect for TRUNCATE. The difference is, truncate logs only deallocation of pages, which is multiple orders of magnitude less (basically insignifficant) compared to DELETE which logs data that is deleted. That is why truncate is &#8222;instant&#8220;. If you delete eg. 10GB of data, you wait for 10GB to be written to transaction log, which takes time. Truncate logs maybe 1KB for deallocation info, which is instant. If you do not want to delete all rows, you can still use TRUNCATE by storing survivor rows aside before truncating, and inserting them back after truncate. Even better, you can use SWITCH into some dummy table (even with not-partitioned tables) to remove rows quickly, and then insert survivor rows back from that dummy into original table. That is the fastest way to delete when a smaller percent of rows needs to survive.</p>



<p><strong>Vedran Kesegic</strong></p>



<p>Obvious difference is that truncate removes all rows from table (&#8222;truncate table&#8220;) or from partition(s), when using &#8222;trancate table xy with partitions (&#8230;)&#8220;. You cannot choose which rows to delete, they all are gone. With delete you can have a WHERE clause to choose which rows to delete. Delete is more appropriate if you need to delete a small percentage of table rows (or partition rows).</p>



<p><strong>Vedran Kesegic</strong></p>



<p>Truncate is a metadata operation, requires a different lock (SCH_M, schema modification lock). If also has some restrictins regarding foreign keys etc. Check the documentation for the list of limitations: https://learn.microsoft.com/en-us/sql/t-sql/statements/truncate-table-transact-sql</p>



<p><strong>Carsten Saastamoinen-Jakobsen</strong></p>



<p>It is not an argument to call TRUNCATE a DDL statement because a certain lock is used! When statements are categorized, it must be based on what happens and not how a given database system solves the task. Data is deleted, the structure is preserved and only some data may be deleted. When one or more partitions are deleted, the condition is also well-known, but just limited. In previous versions of database systems &#8211; and perhaps still &#8211; a TRUNCATE was performed by a DROP TABLE + CREATE TABLE. Hence DDL rights. It just shows that it is problematic to categorize based on how it is performed and not based on what actually happens. If we look at the documentation for SQL Server, it is not mentioned that TRUNCATE is a DDL. We may have to recognize that a previous error categorization should not continue to call TRUNCATE a DDL, but recognize that it is a DML. We will also be free from erroneous claims about only deleting all rows, that space is not released, that the transaction cannot be rolled back, &#8230;. A DELETE operation without a user-defined transaction cannot be rolled back either! But DELETE is DML and not DDL. TRUNCATE is &#8218;created&#8216; for having af fast way of deleting rows, and extended for only deleting some of the rows &#8211; DML!!!</p>



<p><strong>Vedran Kesegic</strong></p>



<p>No, the SCH-M lock (the &#8222;king of all locks&#8220;) is not the sole reason why TRUNCATE is DDL. DML writes data (rows in user tables), while DDL writes metadata (rows in system tables, data that describes other/user objects). Truncate happens to write metadata (system tables) and thus is classified as DDL. See the doc: https://learn.microsoft.com/en-us/previous-versions/sql/sql-server-2012/ff848799(v=sql.110)</p>



<p><strong>Carsten Saastamoinen-Jakobsen</strong></p>



<p>Can you tell which data is written to the system tables that is not written when removing rows by DELETE? The only additional information is, that with TRUNCATE of all rows without specifying partitions is, that the &#8218;identity&#8216; is reset to the initial values. Removing some or all rows with specifying partitions, this value is not reset to the initial value. Empty page are handled in the same way as empty page after DELETE! All indexes are preserved, the table definition is NOT changed, &#8230;.</p>



<p><strong>Vedran Kesegic</strong></p>



<p>Better than that &#8211; you can see for yourself! The exact difference and details are present in transaction log records after you do TRUNCATE and compare that to log records that DELETE generates. Use fn_dblog() function, but only on the test system because it is undocumented and might have an impact.</p>



<p>Or you are trying to say that Microsoft is wrong in documentation? If so, report it to MS so doc can be fixed. But in this case there is nothing to fix.</p>



<p>Or you are trying to argue with SQL Certified Master about SQL? Good luck Mr <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p><strong>Carsten Saastamoinen-Jakobsen</strong></p>



<p>I say that MS is right in the documentations because they are not telling that TRUNCATE is as DDL, because they know that TRUNCATE is a DML!. Of course there is less in the log &#8211; it is the idea wit TRUNCATE!!!!!!!! Just te functionality and te reason for implementing TRUNCATE as an alternative to DELETE. But the log is NOT the system tables!!!!! So please tell which system tables are updated as they are updated when CRAETE, ALTER and DROP but NOT updated when INSERT, DELETE or UPDATE.</p>



<p><strong>Vedran Kesegic</strong></p>



<p>TRUNCATE modifies internal system tables sys.sysallocunits and sys.sysrowsets. DELETE modifies indexes and stats &#8211; see attached pictures. You could do that yourself using fn_dblog as instructed, but I did that for you so you don&#8217;t have to. If you want to know more about deep SQL Server internals you can attend one of my trainings, or trainings of other SQL Masters like Brent Ozar, Paul Randal (sqlskills), etc.</p>



<p><strong>Carsten Saastamoinen-Jakobsen</strong></p>



<p>Of course they are modified as INSERT DELETE and UPDATE modify this informations. But INSERT, DELETE and UPDATE are still only DML and not DDL. And I am not impressed of your job by showing me this information. If you was showing the same for the other DML statements it would be fine. So maybe you should modify your course material and also shows the same for the other DML statements!!!!</p>
</details>



<p></p><p>The post <a href="https://dbavonnebenan.de/sql-server-truncate-vs-delete-dml-or-ddl-de/">TRUNCATE TABLE Operationen im Detail – ROLLBACK ist doch möglich</a> first appeared on <a href="https://dbavonnebenan.de">DBA von Nebenan</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://dbavonnebenan.de/sql-server-truncate-vs-delete-dml-or-ddl-de/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
