{"id":6410,"date":"2026-02-06T08:21:44","date_gmt":"2026-02-06T16:21:44","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sql\/?p=6410"},"modified":"2026-02-23T11:18:55","modified_gmt":"2026-02-23T19:18:55","slug":"mask-data-in-azure-sql","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sql\/mask-data-in-azure-sql\/","title":{"rendered":"Masking Sensitive Data in Azure SQL"},"content":{"rendered":"<p>Applications often need access to data without needing access to everything. Social Security numbers, email addresses, and phone numbers are common examples. Storing them is required. Exposing them broadly is not. This is especially valuable when exposing a database to an AI agent through MCP servers like SQL MCP Server, where safety and reversibility matter.<\/p>\n<blockquote>\n<p>Learn more about <a href=\"https:\/\/aka.ms\/sql\/mcp\">SQL MCP Server<\/a><\/p>\n<\/blockquote>\n<p>Azure SQL includes built-in features that let the database protect sensitive values automatically. The application does not decide what is visible. The database does.<\/p>\n<blockquote>\n<p>Working demo <a href=\"https:\/\/gist.github.com\/JerryNixon\/3a5f5c5cac8a289e685cc84bec50c578\">https:\/\/gist.github.com<\/a><\/p>\n<\/blockquote>\n<h2>What We Are Building<\/h2>\n<p>A table that stores sensitive data and rules that mask that data.<\/p>\n<h2>Step 1: Create the User<\/h2>\n<pre><code class=\"sql\">CREATE USER AppUser WITHOUT LOGIN;\nGO\n<\/code><\/pre>\n<h2>Step 2: Create the Table<\/h2>\n<pre><code class=\"sql\">CREATE TABLE dbo.Customers\n(\n    Id        INT IDENTITY(1,1) PRIMARY KEY,\n    FullName  NVARCHAR(200) NOT NULL,\n    SSN       CHAR(11) NOT NULL,\n    Email     NVARCHAR(256) NOT NULL,\n    Phone     NVARCHAR(20) NOT NULL\n);\nGO\n\nINSERT INTO dbo.Customers (FullName, SSN, Email, Phone) VALUES\n    ('Alex Johnson', '123-45-6789', 'alex@example.com', '555-123-4567'),\n    ('Maria Lopez', '987-65-4321', 'maria@example.com', '555-987-6543');\nGO\n<\/code><\/pre>\n<h2>Step 3: Apply Data Masking<\/h2>\n<p>Dynamic Data Masking hides data at query time. The data stays unchanged in storage.<\/p>\n<h3>Mask Columns<\/h3>\n<pre><code class=\"sql\">-- Mask SSN (123-45-6789 -&gt; XXX-XX-6789)\nALTER TABLE dbo.Customers\nALTER COLUMN SSN\nADD MASKED WITH (FUNCTION = 'partial(0,\"XXX-XX-\",4)');\nGO\n\n-- Mask Email (maria.lopez@contoso.com -&gt; mXXX@XXXXXXX.com)\nALTER TABLE dbo.Customers\nALTER COLUMN Email\nADD MASKED WITH (FUNCTION = 'email()');\nGO\n\n-- Mask Phone (123-456-7890 -&gt; XXX-XXX-7890)\nALTER TABLE dbo.Customers\nALTER COLUMN Phone\nADD MASKED WITH (FUNCTION = 'partial(0,\"XXX-XXX-\",4)');\nGO\n<\/code><\/pre>\n<p>Dynamic Data Masking includes several built-in masking functions. The <code>email()<\/code> function used here is built in and requires no user-defined logic. It preserves the first character of the email name and the top-level domain while masking the rest. Other built-in options include <code>default()<\/code> for full masking, <code>partial()<\/code> for custom prefix and suffix preservation, and <code>random()<\/code> for numeric data. These functions are applied at query time and do not change the underlying stored values.<\/p>\n<h2>Step 4: See It Work<\/h2>\n<h3>Admin view<\/h3>\n<pre><code class=\"sql\">SELECT * FROM dbo.Customers;\n<\/code><\/pre>\n<h4>Result<\/h4>\n<table>\n<thead>\n<tr>\n<th>Id<\/th>\n<th>FullName<\/th>\n<th>SSN<\/th>\n<th>Email<\/th>\n<th>Phone<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>1<\/td>\n<td>Alex Johnson<\/td>\n<td>123-45-6789<\/td>\n<td><a href=\"&#x6d;&#97;&#105;&#x6c;&#116;&#111;&#x3a;&#x61;&#108;&#101;&#x78;&#64;&#101;&#x78;&#x61;&#109;p&#x6c;&#101;&#46;&#x63;&#x6f;&#109;\">&#x61;&#108;&#101;&#x78;&#64;&#101;&#x78;&#x61;&#109;p&#x6c;&#101;&#46;&#x63;&#x6f;&#109;<\/a><\/td>\n<td>555-123-4567<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>Maria Lopez<\/td>\n<td>987-65-4321<\/td>\n<td><a href=\"&#109;&#97;&#x69;&#x6c;&#x74;&#111;&#58;&#x6d;&#x61;&#x72;&#105;&#97;&#x40;&#x65;&#x78;&#97;&#109;&#x70;&#x6c;&#x65;&#46;&#99;&#x6f;&#x6d;\">&#x6d;&#x61;&#x72;&#105;&#97;&#x40;&#x65;&#x78;&#97;&#109;&#x70;&#x6c;&#x65;&#46;&#99;&#x6f;&#x6d;<\/a><\/td>\n<td>555-987-6543<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>User view<\/h3>\n<pre><code class=\"sql\">EXECUTE AS USER = 'AppUser';\nSELECT * FROM dbo.Customers;\nREVERT;\n<\/code><\/pre>\n<h4>Result<\/h4>\n<table>\n<thead>\n<tr>\n<th>Id<\/th>\n<th>FullName<\/th>\n<th>SSN<\/th>\n<th>Email<\/th>\n<th>Phone<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>1<\/td>\n<td>Alex Johnson<\/td>\n<td>XXX-XX-6789<\/td>\n<td><a href=\"&#109;&#97;&#105;&#x6c;&#x74;&#x6f;:&#97;&#88;&#88;&#x58;&#x40;&#x58;&#88;&#88;&#88;&#88;&#x58;&#x58;&#x2e;&#99;&#111;&#109;\">&#97;&#88;&#88;&#x58;&#x40;&#x58;&#88;&#88;&#88;&#88;&#x58;&#x58;&#x2e;&#99;&#111;&#109;<\/a><\/td>\n<td>XXX-XXX-4567<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>Maria Lopez<\/td>\n<td>XXX-XX-4321<\/td>\n<td><a href=\"&#109;&#x61;&#105;&#108;&#x74;&#111;&#x3a;m&#88;&#x58;&#88;&#x40;&#x58;&#88;&#x58;X&#88;&#x58;&#88;&#x2e;&#x63;&#111;&#x6d;\">m&#88;&#x58;&#88;&#x40;&#x58;&#88;&#x58;X&#88;&#x58;&#88;&#x2e;&#x63;&#111;&#x6d;<\/a><\/td>\n<td>XXX-XXX-6543<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The same rows are returned, but sensitive values are masked automatically for the application user.<\/p>\n<h2>Why This Is Safe<\/h2>\n<ul>\n<li>Masking is enforced by the database<\/li>\n<li>Applications cannot bypass it<\/li>\n<li>Storage remains intact for audits and reporting<\/li>\n<li>Admins retain full access<\/li>\n<li>Reduces accidental exposure<\/li>\n<li>Zero application changes<\/li>\n<\/ul>\n<h2>When to Use Something Stronger<\/h2>\n<p>Dynamic Data Masking is not encryption. Privileged users can still see data.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Applications often need access to data without needing access to everything. Social Security numbers, email addresses, and phone numbers are common examples. Storing them is required. Exposing them broadly is not. This is especially valuable when exposing a database to an AI agent through MCP servers like SQL MCP Server, where safety and reversibility matter. [&hellip;]<\/p>\n","protected":false},"author":96788,"featured_media":6605,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[648,710,619],"tags":[560,679,38,711,34],"class_list":["post-6410","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security","category-sql-mcp-server","category-t-sql","tag-data-api-builder","tag-mcp-server","tag-security","tag-sql-mcp-server","tag-t-sql"],"acf":[],"blog_post_summary":"<p>Applications often need access to data without needing access to everything. Social Security numbers, email addresses, and phone numbers are common examples. Storing them is required. Exposing them broadly is not. This is especially valuable when exposing a database to an AI agent through MCP servers like SQL MCP Server, where safety and reversibility matter. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/6410","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/users\/96788"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/comments?post=6410"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/6410\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media\/6605"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media?parent=6410"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/categories?post=6410"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/tags?post=6410"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}