Yes.
Row Level Security - You can apply security directly to individual tables using direct commands. You use ALTER TABLE SET ROW FILTER to attach a UDF that returns true/false for each row, controlling which rows each user can see. It can be applied directly to one table at a time & the filter is transparent to users querying that table. You attach a function to table & it filters data at query time
-- Create filter function
CREATE FUNCTION main.default.dept_filter(dept STRING)
RETURN dept = current_user() OR is_member('admins');
-- Apply to specific table
ALTER TABLE main.default.employees
SET ROW FILTER catalog.schema.dept_filter ON (department);
Column Masks - You use ALTER TABLE SET MASK to attach a UDF that transforms column values such as redacting SSN to XXX controlling what users see in specific columns. Its applied per column on each table & masking happens automatically at query time. You attach function to column & it transforms at query time
-- Create mask function
CREATE FUNCTION main.default.mask_ssn(ssn STRING)
RETURN CASE WHEN is_member('HR') THEN ssn ELSE 'XXX' END;
-- Apply to specific column
ALTER TABLE main.default.employees
SET MASK catalog.schema.mask_ssn ON (ssn_column);
Dynamic Views - You create views with CASE WHEN is_member('group') or current_user() logic embedded in the SELECT statement to conditionally filter rows or mask columns. Users query the view instead of the base table & the security logic lives in the view definition. Its standard view with hardcoded logic like traditional world.
Row Level Security using Dynamic Views
CREATE VIEW main.sales_filtered AS
SELECT *
FROM main.sales_raw
WHERE
-- Show all data to admins
is_member('admins')
-- Show only US data to analysts
OR (is_member('analysts') AND region = 'US')
-- Show only user's own records to sales reps
OR (is_member('sales_reps') AND sales_rep = current_user());
Column Level Security using Dynamic Views
CREATE VIEW main.employees_masked AS
SELECT
employee_id,
name,
-- Mask SSN except for HR
CASE WHEN is_member('HR') THEN ssn ELSE 'XXX' END AS ssn,
-- Mask salary except for Finance
CASE WHEN is_member('Finance') THEN salary ELSE NULL END AS salary,
department
FROM main.employees_raw;
Manual filters/masks secure the base table directly (actual table). Dynamic views create a separate secured object (users must query the view)
Method | Security Location | User Queries |
Row Filter | UDF attached to table | Base table |
| Column Mask | UDF attached to column | Base table |
| Dynamic View | Logic in view SQL | View |