Pro ยท Lesson 5 of 13
Files land on a stage. COPY turns files into table rows. Snowpipe does that continuously.
Sign in to save your place.
A stage is the loading dock. A file format is the packing slip that says whether the boxes are CSV or Parquet. COPY INTO is the crew that unpacks the boxes into shelves. Snowpipe is a crew that starts when a new box arrives, instead of waiting for you to shout.
Internal stages live inside Snowflake: a user stage (@~), a table stage (@%table_name), or a named stage you create. External stages point at Amazon S3, Azure Blob Storage, or Google Cloud Storage that you manage.
File formats cover CSV and other delimited text, JSON, Avro, ORC, Parquet, and XML. Name the format once and reuse it in COPY, so a skipped header or a quote character is not retyped in every load.
A directory table on a stage lists the files themselves. That is the door into unstructured data, covered again in the Iceberg lesson. Enabling it does not by itself parse CSV into columns.
COPY INTO a table reads staged files with a running warehouse. ON_ERROR chooses whether one bad row aborts the file or is skipped. VALIDATION_MODE can preview errors without committing a load. After a successful load, Snowflake remembers which files it already loaded for that table, unless you tell COPY to force them.
Unloading is the reverse: COPY INTO @stage FROM table. Bulk unload to delimited files and JSON is on every edition.
CREATE OR REPLACE FILE FORMAT ff_csv
TYPE = CSV
SKIP_HEADER = 1
FIELD_OPTIONALLY_ENCLOSED_BY = '"';
CREATE OR REPLACE STAGE stg_orders
FILE_FORMAT = ff_csv;
COPY INTO orders
FROM @stg_orders
FILE_FORMAT = (FORMAT_NAME = ff_csv)
ON_ERROR = ABORT_STATEMENT;
Snowpipe is continuous micro-batch loading and is listed for every edition. A pipe wraps a COPY statement. AUTO_INGEST = TRUE waits for a notification from the storage cloud. The notification service is different on AWS, Azure, and Google Cloud, so follow the auto-ingest page for the cloud you chose. Snowpipe compute is serverless. It is not the same bill as LEARN_WH.
Snowpipe Streaming loads rows, not files. Snowflake's current overview describes a high-performance architecture and says the older classic architecture is planned for future deprecation. Use the high-performance path for new work. Elastic Channels are the recommended start: Snowflake manages channels, delivery is at-least-once, and order is not guaranteed. Named Channels are the ordered, exactly-once option and use offset tokens. The docs describe throughput up to 20 GB/s per table and ingest-to-query latency as low as about 5 seconds. Treat those as documented ceilings, not a promise for every account and region.
Fail-safe does not protect tables that contain data loaded by the classic streaming architecture. If you still have classic channels, read that limitation before you count on Fail-safe.
A CSV in a bucket travels through a stage and a COPY command into a table.
Step 1 of 3A stage is a named location: an internal stage inside Snowflake, or an external stage pointing at your S3, Azure or Google Cloud bucket.
LIST @raw_stage;
Step 2 of 3COPY INTO reads the staged files with a file format and writes rows. It remembers which files it loaded for 64 days, so running it again does not duplicate rows.
COPY INTO orders FROM @raw_stage FILE_FORMAT = (TYPE = CSV SKIP_HEADER = 1);
Step 3 of 3Snowpipe runs the same COPY for you when the bucket sends a new-file notification, usually within a minute, on serverless compute.
CREATE PIPE orders_pipe AUTO_INGEST = TRUE AS COPY INTO orders FROM @raw_stage;
This lab stays inside SQL. It creates a format and an internal stage, then loads a row you insert into a staged file using a COPY INTO from a SELECT, so you do not need a local file uploader. When you do have a CSV, upload it with SnowSQL PUT and point COPY at the stage.
USE WAREHOUSE LEARN_WH;
USE DATABASE LEARN_DB;
USE SCHEMA PUBLIC;
CREATE OR REPLACE FILE FORMAT ff_csv
TYPE = CSV
SKIP_HEADER = 1
FIELD_OPTIONALLY_ENCLOSED_BY = '"';
CREATE OR REPLACE STAGE stg_orders
FILE_FORMAT = ff_csv;
COPY INTO @stg_orders/orders.csv
FROM (SELECT 'order_id', 'region', 'amount'
UNION ALL
SELECT '4', 'west', '8')
FILE_FORMAT = (TYPE = CSV FIELD_OPTIONALLY_ENCLOSED_BY = '"')
OVERWRITE = TRUE;
CREATE OR REPLACE TABLE orders_loaded (
order_id NUMBER,
region STRING,
amount NUMBER(10, 2)
);
COPY INTO orders_loaded
FROM @stg_orders/orders.csv
FILE_FORMAT = (FORMAT_NAME = ff_csv)
ON_ERROR = ABORT_STATEMENT;
SELECT * FROM orders_loaded;
Checked against Snowflake documentation in October 2026. Product behavior still depends on your edition, cloud, and region.