← Back to Cheat Sheets
❄️ Snowflake Cheat Sheet
Complete Snowflake reference — warehouses, stages, streams, tasks, time travel, semi-structured data, RBAC, and Snowpark.
Warehouse Management
Create & Configure
CREATE WAREHOUSE etl_wh
WITH WAREHOUSE_SIZE = 'MEDIUM'
AUTO_SUSPEND = 300
AUTO_RESUME = TRUE
INITIALLY_SUSPENDED = TRUE
MIN_CLUSTER_COUNT = 1
MAX_CLUSTER_COUNT = 3
SCALING_POLICY = 'STANDARD';
-- Sizes: XSMALL, SMALL, MEDIUM, LARGE, XLARGE, 2XL, 3XL, 4XL
-- Each size doubles compute & costCreate warehouses with auto-scaling clusters.
Manage Warehouses
ALTER WAREHOUSE etl_wh SET WAREHOUSE_SIZE = 'LARGE';
ALTER WAREHOUSE etl_wh SUSPEND;
ALTER WAREHOUSE etl_wh RESUME;
ALTER WAREHOUSE etl_wh SET AUTO_SUSPEND = 60;
SHOW WAREHOUSES;
DROP WAREHOUSE IF EXISTS temp_wh;
-- Resource monitor
CREATE RESOURCE MONITOR monthly_limit
WITH CREDIT_QUOTA = 500
TRIGGERS
ON 75 PERCENT DO NOTIFY
ON 100 PERCENT DO SUSPEND;Resize, suspend, resume, and set cost controls.
Database Objects
Database & Schema
CREATE DATABASE analytics;
CREATE DATABASE IF NOT EXISTS staging;
USE DATABASE analytics;
CREATE SCHEMA raw;
CREATE SCHEMA curated;
CREATE SCHEMA analytics.reporting;
SHOW DATABASES;
SHOW SCHEMAS IN DATABASE analytics;Organize data with databases and schemas.
Table Types
-- Permanent table (default)
CREATE TABLE orders (id INT, amount FLOAT, ts TIMESTAMP);
-- Transient (no Fail-safe, lower cost)
CREATE TRANSIENT TABLE staging_data (...);
-- Temporary (session-scoped, auto-dropped)
CREATE TEMPORARY TABLE temp_results AS
SELECT * FROM orders WHERE status = 'pending';
-- External table (reads from stage)
CREATE EXTERNAL TABLE ext_data
WITH LOCATION = @my_stage
FILE_FORMAT = (TYPE = 'PARQUET');Permanent, transient, temporary, and external tables.
Sequences & Tags
CREATE SEQUENCE order_seq START = 1 INCREMENT = 1;
SELECT order_seq.NEXTVAL;
-- Tags for governance
CREATE TAG pii_level ALLOWED_VALUES 'HIGH', 'MEDIUM', 'LOW';
ALTER TABLE users SET TAG pii_level = 'HIGH';
ALTER TABLE users MODIFY COLUMN email SET TAG pii_level = 'HIGH';Auto-increment sequences and governance tags.
Data Loading
Stages
-- Internal stage
CREATE STAGE my_internal_stage;
PUT file:///tmp/data.csv @my_internal_stage;
-- External S3 stage
CREATE STAGE my_s3_stage
URL = 's3://bucket/path/'
STORAGE_INTEGRATION = my_s3_int;
-- External GCS stage
CREATE STAGE my_gcs_stage
URL = 'gcs://bucket/path/'
STORAGE_INTEGRATION = my_gcs_int;
-- External Azure stage
CREATE STAGE my_az_stage
URL = 'azure://account.blob.core.windows.net/container/'
STORAGE_INTEGRATION = my_az_int;
LIST @my_s3_stage;Internal and external stages for all cloud providers.
File Formats
CREATE FILE FORMAT csv_fmt
TYPE = 'CSV'
FIELD_DELIMITER = ','
SKIP_HEADER = 1
NULL_IF = ('NULL', 'null', '')
FIELD_OPTIONALLY_ENCLOSED_BY = '"'
ERROR_ON_COLUMN_COUNT_MISMATCH = FALSE;
CREATE FILE FORMAT json_fmt TYPE = 'JSON' STRIP_OUTER_ARRAY = TRUE;
CREATE FILE FORMAT parquet_fmt TYPE = 'PARQUET';
CREATE FILE FORMAT avro_fmt TYPE = 'AVRO';Define reusable format specs for CSV, JSON, Parquet, Avro.
COPY INTO
-- Load from stage
COPY INTO my_table
FROM @my_s3_stage/data/
FILE_FORMAT = (FORMAT_NAME = csv_fmt)
PATTERN = '.*\.csv'
ON_ERROR = 'CONTINUE';
-- Load with transformations
COPY INTO my_table (id, name, created)
FROM (
SELECT $1, UPPER($2), TO_TIMESTAMP($3)
FROM @my_stage
)
FILE_FORMAT = csv_fmt;
-- Unload to stage
COPY INTO @my_stage/export/
FROM my_table
FILE_FORMAT = (TYPE = 'PARQUET')
HEADER = TRUE;Load and unload data with transformations.
Snowpipe
CREATE PIPE my_pipe
AUTO_INGEST = TRUE
AS
COPY INTO my_table
FROM @my_s3_stage
FILE_FORMAT = csv_fmt;
-- Check pipe status
SELECT SYSTEM$PIPE_STATUS('my_pipe');
-- Refresh manually
ALTER PIPE my_pipe REFRESH;Continuous auto-ingestion from cloud storage.
Streams & Tasks
Streams (CDC)
CREATE STREAM orders_stream ON TABLE raw.orders;
-- Query changes since last DML consumption
SELECT * FROM orders_stream;
-- Metadata columns:
-- METADATA$ACTION (INSERT / DELETE)
-- METADATA$ISUPDATE (TRUE for UPDATE)
-- METADATA$ROW_ID
-- Append-only stream (inserts only)
CREATE STREAM inserts_only
ON TABLE raw.events
APPEND_ONLY = TRUE;
-- Check if stream has data
SELECT SYSTEM$STREAM_HAS_DATA('orders_stream');Capture CDC — inserts, updates, deletes.
Tasks
-- Scheduled task
CREATE TASK hourly_load
WAREHOUSE = etl_wh
SCHEDULE = 'USING CRON 0 * * * * UTC'
WHEN SYSTEM$STREAM_HAS_DATA('orders_stream')
AS
INSERT INTO curated.orders
SELECT * FROM orders_stream WHERE METADATA$ACTION = 'INSERT';
-- Child task (DAG)
CREATE TASK transform_task
WAREHOUSE = etl_wh
AFTER hourly_load
AS
CALL transform_procedure();
-- Manage tasks
ALTER TASK hourly_load RESUME;
ALTER TASK hourly_load SUSPEND;
-- Monitor
SELECT * FROM TABLE(INFORMATION_SCHEMA.TASK_HISTORY())
ORDER BY SCHEDULED_TIME DESC LIMIT 20;Schedule SQL/procedures with task DAGs.
Time Travel & Cloning
Time Travel
-- Query data as of N seconds ago
SELECT * FROM my_table AT (OFFSET => -3600);
-- Query at specific timestamp
SELECT * FROM my_table AT (TIMESTAMP => '2024-07-01 12:00:00'::TIMESTAMP);
-- Query before a specific statement
SELECT * FROM my_table BEFORE (STATEMENT => '<query_id>');
-- Restore dropped table
UNDROP TABLE accidentally_dropped;
UNDROP SCHEMA dropped_schema;
UNDROP DATABASE dropped_db;
-- Set retention period (Enterprise: up to 90 days)
ALTER TABLE my_table SET DATA_RETENTION_TIME_IN_DAYS = 30;Query historical data and restore dropped objects.
Zero-Copy Cloning
CREATE TABLE orders_backup CLONE orders;
CREATE SCHEMA dev_schema CLONE prod_schema;
CREATE DATABASE dev_db CLONE prod_db;
-- Clone at a point in time
CREATE TABLE restored CLONE my_table
AT (TIMESTAMP => '2024-07-01 12:00:00'::TIMESTAMP);Instant, storage-efficient clones with time travel support.
Semi-Structured Data
VARIANT & Dot Notation
-- Column type for JSON / XML / Avro
CREATE TABLE events (id INT, data VARIANT);
-- Access nested fields
SELECT
data:user:name::STRING AS user_name,
data:user:age::INT AS age,
data:items[0]:product::STRING AS first_product
FROM events;Store and query nested JSON in VARIANT columns.
LATERAL FLATTEN
-- Flatten array to rows
SELECT
e.id,
f.value:name::STRING AS item_name,
f.value:qty::INT AS quantity
FROM events e,
LATERAL FLATTEN(input => e.data:items) f;
-- Flatten nested object keys
SELECT
f.key AS metric_name,
f.value::FLOAT AS metric_value
FROM events e,
LATERAL FLATTEN(input => e.data:metrics) f;Explode arrays and objects into relational rows.
PARSE_JSON & OBJECT_CONSTRUCT
SELECT PARSE_JSON('{"a":1, "b":2}') AS j;
SELECT OBJECT_CONSTRUCT(
'name', name,
'dept', department,
'salary', salary
) AS json_obj
FROM employees;
SELECT ARRAY_CONSTRUCT(1, 2, 3) AS arr;
SELECT ARRAY_AGG(name) WITHIN GROUP (ORDER BY name) FROM employees;Build JSON objects and arrays from relational data.
Procedures & UDFs
Stored Procedure (SQL)
CREATE OR REPLACE PROCEDURE merge_data(src STRING, tgt STRING)
RETURNS STRING
LANGUAGE SQL
AS
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO ' || tgt || ' SELECT * FROM ' || src;
RETURN 'Loaded ' || src || ' into ' || tgt;
END;SQL-based stored procedures.
Stored Procedure (Python)
CREATE OR REPLACE PROCEDURE process_data(table_name STRING)
RETURNS STRING
LANGUAGE PYTHON
RUNTIME_VERSION = '3.11'
PACKAGES = ('snowflake-snowpark-python')
HANDLER = 'run'
AS $$
def run(session, table_name):
df = session.table(table_name)
result = df.filter(df['status'] == 'active').count()
return f'Active rows: {result}'
$$;Python stored procedures with Snowpark.
UDF & UDTF
-- Scalar UDF
CREATE FUNCTION celsius_to_f(c FLOAT)
RETURNS FLOAT
LANGUAGE SQL
AS 'c * 9/5 + 32';
-- Python UDF
CREATE FUNCTION classify_salary(salary FLOAT)
RETURNS STRING
LANGUAGE PYTHON
RUNTIME_VERSION = '3.11'
HANDLER = 'classify'
AS $$
def classify(salary):
if salary > 100000: return 'Senior'
elif salary > 60000: return 'Mid'
return 'Junior'
$$;
SELECT name, classify_salary(salary) FROM employees;Scalar UDFs in SQL or Python for reusable logic.
Access Control (RBAC)
Roles & Grants
CREATE ROLE analyst_role;
CREATE ROLE etl_role;
GRANT USAGE ON WAREHOUSE etl_wh TO ROLE etl_role;
GRANT USAGE ON DATABASE analytics TO ROLE analyst_role;
GRANT SELECT ON ALL TABLES IN SCHEMA analytics.public TO ROLE analyst_role;
GRANT SELECT ON FUTURE TABLES IN SCHEMA analytics.public TO ROLE analyst_role;
GRANT ROLE analyst_role TO USER mukesh;
-- Role hierarchy
GRANT ROLE analyst_role TO ROLE sysadmin;Role-based access control with future grants.
Data Sharing
-- Provider
CREATE SHARE my_share;
GRANT USAGE ON DATABASE analytics TO SHARE my_share;
GRANT SELECT ON TABLE analytics.public.reports TO SHARE my_share;
ALTER SHARE my_share ADD ACCOUNTS = consumer_account;
-- Consumer
CREATE DATABASE shared_data FROM SHARE provider.my_share;Share data securely across Snowflake accounts.
Dynamic Tables & Materialized Views
Dynamic Tables
CREATE DYNAMIC TABLE curated_orders
TARGET_LAG = '1 hour'
WAREHOUSE = etl_wh
AS
SELECT
o.id, c.name, o.amount, o.order_date
FROM raw.orders o
JOIN raw.customers c ON o.customer_id = c.id
WHERE o.status = 'completed';
-- Snowflake auto-refreshes based on target lag
ALTER DYNAMIC TABLE curated_orders REFRESH;Declarative pipelines — Snowflake auto-manages refresh.
Materialized Views
CREATE MATERIALIZED VIEW mv_daily_revenue AS
SELECT DATE_TRUNC('day', order_date) AS day,
SUM(amount) AS revenue
FROM orders
GROUP BY 1;
-- Auto-maintained by Snowflake on base table changes
-- Best for: small aggregation result sets with frequent readsPre-computed views auto-maintained by Snowflake.
Query Profiling & Optimization
Query History & Profile
-- Recent queries
SELECT query_id, query_text, execution_status,
total_elapsed_time/1000 AS seconds,
bytes_scanned, rows_produced
FROM TABLE(INFORMATION_SCHEMA.QUERY_HISTORY())
ORDER BY start_time DESC LIMIT 20;
-- Expensive queries
SELECT * FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY
WHERE TOTAL_ELAPSED_TIME > 60000 -- > 60 seconds
ORDER BY TOTAL_ELAPSED_TIME DESC;Find slow and expensive queries.
Clustering & Optimization
-- Clustering keys (for large tables)
ALTER TABLE orders CLUSTER BY (order_date, region);
-- Check clustering info
SELECT SYSTEM$CLUSTERING_INFORMATION('orders', '(order_date)');
-- Search optimization
ALTER TABLE orders ADD SEARCH OPTIMIZATION
ON EQUALITY(customer_id)
ON SUBSTRING(product_name);Cluster keys and search optimization for large tables.