<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Regular-Expressions | The .NET Blog</title><link>https://thedotnetblog.com/tags/regular-expressions/</link><description>Articles, tutorials and insights from the .NET community.</description><generator>Hugo</generator><language>en</language><managingEditor>@thedotnetblog (The .NET Blog)</managingEditor><webMaster>@thedotnetblog</webMaster><lastBuildDate>Fri, 11 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://thedotnetblog.com/tags/regular-expressions/index.xml" rel="self" type="application/rss+xml"/><item><title>T-SQL Regex on 2 MB Blobs: No More Truncation, Less Application Code</title><link>https://thedotnetblog.com/news/emiliano-montesdeoca/azure-sql-regex-lob-types/</link><pubDate>Fri, 11 Sep 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/news/emiliano-montesdeoca/azure-sql-regex-lob-types/</guid><description>Azure SQL and SQL Server 2025 CU5 extend all seven native T-SQL regex functions to varchar(max) and nvarchar(max) inputs up to 2 MB.</description><content:encoded>&lt;p&gt;Original source: &lt;a href="https://devblogs.microsoft.com/azure-sql/regex-support-for-lob-types-in-t-sql-available-in-azure-sql-sql-server-2025/"&gt;Regex support for LOB types in T-SQL—available in Azure SQL &amp;amp; SQL Server 2025&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="the-problem-this-removes"&gt;The Problem This Removes&lt;/h2&gt;
&lt;p&gt;A table full of logs, HTML documents, or large JSON payloads often leads to an awkward split: the database stores the text, while .NET code exports it for pattern matching, redaction, or extraction. That adds network round-trips and scatters data-processing logic across two layers.&lt;/p&gt;
&lt;p&gt;Native T-SQL regex already reduced that need, but large-object support was incomplete. SQL Server 2025 CU5 closes the gap: all seven regex functions accept &lt;code&gt;varchar(max)&lt;/code&gt; and &lt;code&gt;nvarchar(max)&lt;/code&gt; inputs up to 2 MB. Azure SQL Database, SQL Database in Fabric, and Azure SQL Managed Instance with the relevant update policy also support the capability.&lt;/p&gt;
&lt;p&gt;The practical result is that common logs, HTML pages, and JSON payloads no longer need to be truncated to 8,000 bytes or split merely to run a regex operation.&lt;/p&gt;
&lt;h2 id="what-changed-in-cu5"&gt;What Changed in CU5&lt;/h2&gt;
&lt;p&gt;At the original SQL Server 2025 general availability release, LOB inputs were supported on &lt;code&gt;REGEXP_LIKE&lt;/code&gt;, &lt;code&gt;REGEXP_COUNT&lt;/code&gt;, and &lt;code&gt;REGEXP_INSTR&lt;/code&gt;. The remaining scalar functions and table-valued functions required non-LOB strings. CU5 brings all seven functions to the same 2 MB input limit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;REGEXP_LIKE&lt;/code&gt; filters rows.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REGEXP_COUNT&lt;/code&gt; counts occurrences.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REGEXP_INSTR&lt;/code&gt; locates a match.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REGEXP_REPLACE&lt;/code&gt; redacts or cleanses text.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REGEXP_SUBSTR&lt;/code&gt; extracts one value.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REGEXP_MATCHES&lt;/code&gt; returns matches and capture groups as rows.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REGEXP_SPLIT_TO_TABLE&lt;/code&gt; shreds text into rows by a regex delimiter.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The pattern remains capped at 8,000 bytes. The 2 MB limit applies to the input passed to one function call, not to the maximum size of the &lt;code&gt;varchar(max)&lt;/code&gt; or &lt;code&gt;nvarchar(max)&lt;/code&gt; column.&lt;/p&gt;
&lt;p&gt;The engine uses RE2, a linear-time, non-backtracking implementation. That matters when patterns run against large or untrusted text because the engine avoids catastrophic backtracking behavior.&lt;/p&gt;
&lt;h2 id="the-set-based-advantage"&gt;The Set-Based Advantage&lt;/h2&gt;
&lt;p&gt;The source&amp;rsquo;s examples use a &lt;code&gt;LogEntries&lt;/code&gt; table with a &lt;code&gt;RawPayload&lt;/code&gt; &lt;code&gt;varchar(max)&lt;/code&gt; column. The same payload can be filtered for HTTP 5xx responses, counted for request methods, searched for the first error position, or passed through nested &lt;code&gt;REGEXP_REPLACE&lt;/code&gt; calls to redact credit-card, SSN, and email-shaped values.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;REGEXP_MATCHES&lt;/code&gt; is especially useful when the output should become relational data. It returns one row per match, including the matched value and JSON describing capture groups. &lt;code&gt;REGEXP_SPLIT_TO_TABLE&lt;/code&gt; can turn a multi-line payload into one row per line. Those results can feed a CTE, an aggregate, a join, or a staging table without first moving the document into application memory.&lt;/p&gt;
&lt;p&gt;For a .NET application, this can simplify the boundary. If the transformation is fundamentally a database filter or cleanse, keep it close to the data and return the smaller result set to the application. That does not mean every regex belongs in SQL. Business rules that depend on domain services, external APIs, or rich application types may still belong in C#.&lt;/p&gt;
&lt;h2 id="prerequisites-to-check"&gt;Prerequisites to Check&lt;/h2&gt;
&lt;p&gt;SQL Server requires CU5 or later. The feature is also available in the Azure SQL services described by the source, with Managed Instance availability depending on the update policy and regional rollout.&lt;/p&gt;
&lt;p&gt;The two table-valued functions require compatibility level 170 unless the preview database-scoped configuration that enables built-in TVFs at other levels is used. The source also notes that &lt;code&gt;REGEXP_LIKE&lt;/code&gt; requires compatibility level 170, while the other scalar functions are available at all compatibility levels.&lt;/p&gt;
&lt;p&gt;Check the database before changing a query:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;compatibility_level&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;databases&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DB_NAME&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The 2 MB ceiling is measured in UTF-8 bytes, not simply characters. ASCII input can approach two million characters, while non-ASCII text consumes more bytes. A value above &lt;code&gt;2 * 1024 * 1024&lt;/code&gt; bytes is rejected with error 19311 rather than silently truncated. If individual values are larger, split them into logical units at ingestion rather than inventing a query-time workaround.&lt;/p&gt;
&lt;h2 id="a-better-net-decision-boundary"&gt;A Better .NET Decision Boundary&lt;/h2&gt;
&lt;p&gt;If the current code reads a large database value into .NET only to run a regex, audit it. A SQL-side implementation may reduce I/O, application CPU, and synchronization risk. Compare query plans and database resource usage; moving work into SQL is not automatically cheaper when the pattern is expensive or the data is poorly indexed.&lt;/p&gt;
&lt;p&gt;Keep parameterization and authorization intact. A regex operation can cleanse data, but it does not replace access control or validation. Test multiline flags, capture-group semantics, Unicode behavior, and the exact byte-size boundary with representative payloads.&lt;/p&gt;
&lt;h2 id="recommendations"&gt;Recommendations&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Inventory application code that exports database text only for regex processing.&lt;/li&gt;
&lt;li&gt;Test the seven functions on Azure SQL or SQL Server 2025 CU5 with representative LOBs.&lt;/li&gt;
&lt;li&gt;Verify compatibility level and the 2 MB UTF-8 byte limit.&lt;/li&gt;
&lt;li&gt;Keep oversized values logically partitioned at ingestion.&lt;/li&gt;
&lt;li&gt;Compare SQL and .NET performance before moving high-volume transformations.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;CU5 completes the native regex story for large objects. The useful change is not merely that a bigger string is accepted; it is that filtering, extraction, redaction, and shredding can remain set-based and close to the data.&lt;/p&gt;</content:encoded></item></channel></rss>