Snowflake's two core data-protection features, Masking Policy and Row Access Policy, are both policy-based access controls available on Enterprise Edition and above, but they target fundamentally different things. Masking Policy transforms the value of a column, while Row Access Policy filters the visibility of rows. Using both correctly — and combining them when needed — is required knowledge for the SnowPro Security exam and for real-world deployments.
| Dimension | Masking Policy | Row Access Policy |
|---|---|---|
| Target of control | Column value (transforms column values) | Row visibility (filters records) |
| Return type | Same data type as input (returns masked value) | BOOLEAN (TRUE = visible / FALSE = hidden) |
| Attach target | One per column | One per table or view |
| Behavior with SELECT * | Masked values are returned | Only filtered rows are returned |
| Impact on COUNT(*) | No impact (row count is unchanged) | Returns the post-filter row count |
| Behavior in WHERE clause | Filtering runs against pre-mask values | WHERE clause is applied after the policy filter |
| Tag-based application | Auto-applied via ALTER TAG SET MASKING POLICY | Auto-applied via ALTER TAG SET ROW ACCESS POLICY |
| Required privileges | CREATE MASKING POLICY + APPLY MASKING POLICY | CREATE ROW ACCESS POLICY + APPLY ROW ACCESS POLICY |
-- Mask email addresses
CREATE OR REPLACE MASKING POLICY mask_email
AS (val VARCHAR) RETURNS VARCHAR →
CASE
WHEN IS_ROLE_IN_SESSION('HR_ADMIN') THEN val
WHEN IS_ROLE_IN_SESSION('MANAGER') THEN
CONCAT(LEFT(val, 2), '****@', SPLIT_PART(val, '@', 2))
ELSE '****@****.***'
END;
-- Attach to a column
ALTER TABLE hr.employees
ALTER COLUMN email
SET MASKING POLICY mask_email;
-- Numeric salary masking
CREATE OR REPLACE MASKING POLICY mask_salary
AS (val NUMBER) RETURNS NUMBER →
CASE
WHEN IS_ROLE_IN_SESSION('HR_ADMIN') THEN val
WHEN IS_ROLE_IN_SESSION('MANAGER') THEN
ROUND(val, -4) -- Round to nearest 10,000
ELSE NULL
END;
ALTER TABLE hr.employees
ALTER COLUMN salary
SET MASKING POLICY mask_salary;-- Department-based row filter
CREATE OR REPLACE ROW ACCESS POLICY rap_department
AS (dept_val VARCHAR) RETURNS BOOLEAN →
IS_ROLE_IN_SESSION('HR_ADMIN')
OR dept_val = (
SELECT department FROM hr.user_dept_mapping
WHERE user_name = CURRENT_USER()
);
-- Attach to the table
ALTER TABLE hr.employees
ADD ROW ACCESS POLICY rap_department ON (department);A Masking Policy and a Row Access Policy can be applied to the same table simultaneously. In that case, they are evaluated in the order Row Access Policy → Masking Policy.
-- Scenario: apply both to the hr.employees table
-- Row Access Policy: only show employees in the user's own department
-- Masking Policy: mask the salary column depending on the role
-- Step 1: attach the Row Access Policy
ALTER TABLE hr.employees
ADD ROW ACCESS POLICY rap_department ON (department);
-- Step 2: attach the Masking Policies
ALTER TABLE hr.employees
ALTER COLUMN salary
SET MASKING POLICY mask_salary;
ALTER TABLE hr.employees
ALTER COLUMN email
SET MASKING POLICY mask_email;
-- Result (for the MANAGER role):
-- 1. Row Access Policy narrows the result to the user's own department
-- 2. salary column is rounded to the nearest 10,000
-- 3. email column is returned as the first 2 characters plus a masked suffix| Dimension | Masking / Row Access Policy | Secure View |
|---|---|---|
| Scope | Applies to every access path to the table | Only access through the view |
| Hiding the view definition | Policy logic is visible only to the owner | View definition is hidden from GET_DDL |
| Optimizer behavior | Standard optimizations apply | Some optimizations are restricted |
| Management cost | Managed via table + policy | May require a separate view per role |
| Compatibility with Data Sharing | Policies remain effective for consumers | Secure Views are recommended for Data Sharing |
Requirement: restrict data for specific users or roles
│
├─ Restrict at the row level (e.g., show only employees in the user's department)
│ └─ → Row Access Policy
│
├─ Transform column values before returning (e.g., mask part of an SSN)
│ └─ → Masking Policy
│
├─ Completely hide a column
│ ├─ Drop the column from query results → Projection Policy
│ └─ Drop the column from a view → Secure View
│
└─ Both row restriction + column masking
└─ → Combine Row Access Policy + Masking Policy-- Switch masking based on the value of another column
CREATE OR REPLACE MASKING POLICY mask_salary_by_region
AS (salary_val NUMBER, region_val VARCHAR) RETURNS NUMBER →
CASE
WHEN IS_ROLE_IN_SESSION('HR_ADMIN') THEN salary_val
WHEN IS_ROLE_IN_SESSION('APAC_MANAGER')
AND region_val = 'APAC' THEN salary_val
ELSE NULL
END;
-- Attach by mapping the two columns
ALTER TABLE hr.employees
ALTER COLUMN salary
SET MASKING POLICY mask_salary_by_region
USING (salary, region);Security & Governance
問題 1
The hr.employees table has both a Row Access Policy (showing only the user's own department via the department column) and a Masking Policy (NULL-ing the salary column) applied simultaneously. A user with ANALYST_ROLE (Engineering department) runs SELECT department, salary, COUNT(*) OVER() FROM hr.employees. Which result is correct?
正解: B
Row Access Policy and Masking Policy can be applied simultaneously. The Row Access Policy is evaluated first, leaving only the Engineering department rows. The Masking Policy is then applied, converting the salary column to NULL. COUNT(*) OVER() returns the row count after the Row Access Policy is applied (the Engineering department's row count). This evaluation order (Row Access → Masking) is enforced internally by Snowflake.
When both a Masking Policy and a Row Access Policy are applied, which is evaluated first?
Snowflake evaluates the Row Access Policy first, then applies the Masking Policy to rows that pass the filter. This order is hard-coded inside Snowflake and cannot be changed by users. For example, if a row is filtered out by the Row Access Policy, the Masking Policy for that row is never evaluated (since the row itself is not in the result set).
Should permissions for Masking Policy and Row Access Policy be separated?
Yes. In Snowflake, APPLY MASKING POLICY and APPLY ROW ACCESS POLICY are managed as separate privileges. Separating policy OWNERSHIP (create/modify rights) from APPLY (table-attach rights) enables proper separation of duties. For example, the security team can create policies (OWNERSHIP) while data engineers apply them to individual tables (APPLY).
Can a Secure View replace Masking Policy or Row Access Policy?
Secure Views can exclude columns or filter rows in a WHERE clause, but they have no effect when the underlying table is queried directly or accessed via paths other than the view. Masking Policy and Row Access Policy are attached to the table itself, so they apply to all access paths: direct queries, views, stored procedures, and more. Use Secure Views when you need to hide the view definition, but design your data protection strategy primarily around policies.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
Snowflake Certifications: All 11 Exams Explained (2026)
Every SnowPro certification — Associate, Core, Specialty, Ad...
Snowflake Exam Difficulty Ranking: All 11 Certs Compared (2026)
All 11 SnowPro exams ranked by difficulty with study-time es...
Snowflake Study Guide: Fastest Pass Route by Exam (2026)
How to pass SnowPro certifications efficiently — official ma...
SnowPro Core (COF-C03): Complete Exam Guide (2026)
Pass the SnowPro Core exam — six domains, scope, sample ques...
SnowPro Associate Platform (SOL-C01): Complete Guide (2026)
The entry-level SnowPro Associate exam — scope, weighting, s...