> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-8c05c8a2.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Documentation for Masking Policy

# CREATE MASKING POLICY

export const CloudOnlyBadge = () => {
  return <div className="cloudBadge">
            <div className="cloudIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path fillRule="evenodd" clipRule="evenodd" d="M5.33395 12.6667H12.3739C13.6593 12.6667 14.7073 11.6187 14.7073 10.3334C14.7073 9.04804 13.6593 8.00004 12.3739 8.00004H12.0839V7.33337C12.0839 5.12671 10.2906 3.33337 8.08395 3.33337C6.09928 3.33337 4.45395 4.78537 4.14195 6.68204C2.55728 6.76271 1.29395 8.06204 1.29395 9.66671C1.29395 11.3234 2.63728 12.6667 4.29395 12.6667H5.33395Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
        </div>
            {'ClickHouse Cloud only'}
        </div>;
};

Creates a masking policy, which allows dynamically transforming or masking column values for specific users or roles when they query a table.

<Tip>
  Masking policies provide column-level data security by transforming sensitive data at query time without modifying the stored data.
</Tip>

Syntax:

```sql theme={null}
CREATE MASKING POLICY [IF NOT EXISTS | OR REPLACE] policy_name ON [database.]table
    UPDATE column1 = expression1 [, column2 = expression2 ...]
    [WHERE condition]
    TO {role1 [, role2 ...] | ALL | ALL EXCEPT role1 [, role2 ...]}
    [PRIORITY priority_number]
```

<h2 id="update-clause">
  UPDATE Clause
</h2>

The `UPDATE` clause specifies which columns to mask and how to transform them. You can mask multiple columns in a single policy.

Examples:

* Simple masking: `UPDATE email = '***masked***'`
* Partial masking: `UPDATE email = concat(substring(email, 1, 3), '***@***.***')`
* Hash-based masking: `UPDATE email = concat('masked_', substring(hex(cityHash64(email)), 1, 8))`
* Multiple columns: `UPDATE email = '***@***.***', phone = '***-***-****'`

<h2 id="where-clause">
  WHERE Clause
</h2>

The optional `WHERE` clause allows conditional masking based on row values. Only rows matching the condition will have the masking applied.

Example:

```sql theme={null}
CREATE MASKING POLICY mask_high_salaries ON employees
UPDATE salary = 0
WHERE salary > 100000
TO analyst;
```

<h2 id="to-clause">
  TO Clause
</h2>

In the `TO` section, specify which users and roles the policy should apply to.

* `TO user1, user2`: Apply to specific users/roles
* `TO ALL`: Apply to all users
* `TO ALL EXCEPT user1, user2`: Apply to all users except specified ones

<Note>
  Unlike row policies, masking policies do not affect users who don't have the policy applied. If no masking policy applies to a user, they see the original data.
</Note>

<h2 id="priority-clause">
  PRIORITY Clause
</h2>

When multiple masking policies target the same column for a user, the `PRIORITY` clause determines the application order. Policies are applied in order from highest to lowest priority.

Default priority is 0. Policies with the same priority are applied in an undefined order.

Example:

```sql theme={null}
-- Applied second (lower priority)
CREATE MASKING POLICY mask1 ON users
UPDATE email = 'low@priority.com'
TO analyst
PRIORITY 1;

-- Applied first (higher priority)
CREATE MASKING POLICY mask2 ON users
UPDATE email = 'high@priority.com'
TO analyst
PRIORITY 10;

-- analyst sees 'low@priority.com' because it's applied last
```

<Info>
  **Performance Considerations**

  * Masking policies may impact query performance depending on expression complexity
  * Some optimizations may be disabled for tables with active masking policies
</Info>
