Stream enrichment¶
Part of Streaming Transformations. See all pages in this section.
LEFT OUTER JOIN clauses join the incoming stream to dimension tables, annotating each ingested record with reference data — for example, a customer tier or a product category — without preprocessing in the upstream source.
Dimension table data is loaded into a per-pipe snapshot and refreshed periodically during active ingestion. Updates to a dimension table may be reflected with a delay of up to several minutes.
Dimension table requirements¶
The following requirements apply to each dimension table. Snowflake validates these conditions at pipe creation time; CREATE PIPE fails if they are not met.
| Requirement | Detail |
|---|---|
| Object type | Standard Snowflake tables. For materialized views, dynamic tables, Interactive tables, and supported standard views, contact your Snowflake account team to enable the required capabilities. |
| Primary key | For standard Snowflake tables, the dimension table must have a declared PRIMARY KEY RELY covering all columns referenced in the ON clause. |
| Cardinality | The join must produce at most one matching row per stream record. This is guaranteed when the ON clause exactly covers the table’s primary key. |
| Table size | Initially up to approximately 1 GB per dimension table, ramping to approximately 10 GB per dimension table. |
| Duplicate joins | The same dimension table may not appear more than once in the same pipe definition. |
| Privilege | The pipe owner role must have SELECT on the dimension table. |
| Location | The dimension table may reside in any database or schema visible to the pipe owner role. Cross-cloud and cross-region dimension tables are not supported. |
Declaring a primary key with RELY¶
Primary key constraints on standard Snowflake tables are not enforced or maintained by Snowflake. The RELY property specifies that the constraint should be taken into account during query rewriting. Snowpipe Streaming extends this: RELY is also used at PIPE creation time to validate that a dimension table is a suitable join target, and at ingest time to guide the enrichment lookup.
If you have ensured that the data in the dimension table complies with the PRIMARY KEY constraint, set RELY to indicate that Snowflake should expect such data integrity. For standard tables, it is your responsibility to enforce RELY constraints; otherwise, you might risk unintended behavior and unexpected results. If the RELY property is set and the primary key values in the dimension table are not unique, enrichment results for affected records are undefined.
If the dimension table does not already have a primary key declared with RELY, add one before creating the PIPE:
ON clause requirements¶
Treat each dimension join as a key-value lookup: the ON clause matches on the dimension table’s primary key and returns at most one matching row per stream record.
- The
ONclause must be a pure equi-join that exactly covers the dimension table primary key:<stream_col> = <dim_pk_col>. - Composite primary keys are supported by combining equality conditions with
AND:ON s.$1:k1::STRING = d.dim_pk_col1 AND s.$1:k2::INT = d.dim_pk_col2. - Stream column references use the positional
$nnotation qualified by the stream alias (e.g.s.$1:customer_id). - Extra predicates are not allowed in the
ONclause. Additional conditions in theONclause involving dimension or stream columns beyond the PK equality are rejected. - Expressions, scalar functions, and subqueries are not allowed in the
ONclause.
JOIN semantics¶
LEFT OUTER JOIN semantics apply:
- The
ONclause must exactly cover the dimension table’s primary key. - If a matching row exists in the dimension table snapshot, its columns are added to the output record.
- If no matching row exists, dimension table columns for that record are set to
NULL. The record still ingests; it is not dropped. UseCOALESCEin theSELECTlist to substitute a default value. - Dimension table data is loaded from a per-pipe snapshot. The snapshot is refreshed periodically while the
PIPEis actively ingesting. Staleness may be up to several minutes relative to the current state of the dimension table. - Snapshot refresh does not occur when the pipe is idle (no ingestion traffic for approximately 1.5 minutes). The snapshot is refreshed again when ingestion resumes.
SELECT list for enrichment¶
| Capability | Supported |
|---|---|
Dimension table columns in SELECT | Yes |
| XML or JSON extraction functions | Yes (e.g. XMLGET, PARSE_XML, PARSE_JSON, JSON_EXTRACT_PATH_TEXT) |
| Built-in scalar functions on stream or dimension columns | Yes (e.g. CAST, TRY_CAST, UPPER, IFF, COALESCE) |
Column aliases (AS) | Yes |
SELECT * | Not supported when dimension joins are present; all output columns must be listed explicitly |
MATCH_BY_COLUMN_NAME | Not supported when dimension joins are present |
Example — Single dimension join (customer tier lookup)¶
Example — Multiple dimension joins¶
Enrich each event with user name and city name from separate dimension tables:
Tip
Use explicit column aliases (e.g. AS user_name) when multiple dimension tables could produce columns with the same name.
Example — Combined filter and enrichment¶
Ingest only high-value orders from EU customers and enrich with customer tier:
Usage notes¶
- In pipes that include dimension joins, stream column references in the
SELECT,ON, andWHEREclauses must be qualified with the stream alias (for example,s.$1:customer_id::STRING). Metadata columns such asMETADATA$FILENAMEandMETADATA$START_SCAN_TIMEmay also be referenced inWHEREpredicates. - Dimension snapshots are not refreshed while a pipe is idle. Ingestion is held until a valid snapshot is available; it resumes automatically once the snapshot is ready.
- Streaming Transformations loads dimension table data into a per-pipe snapshot and refreshes it periodically while the
PIPEis actively ingesting. Updates committed to the dimension table may not be visible immediately; staleness of up to several minutes is expected. Different ingest workers within the same pipe may briefly enrich against different snapshot versions. - If a dimension table is dropped or the
PIPEowner role losesSELECTaccess after the pipe is created, the pipe suspends with an error. Restore access and resume the pipe to continue ingestion. INNER JOINisn’t supported. To keep only matched rows, useLEFT OUTER JOINandWHEREon a dimension key withIS NOT NULL.
Limitations¶
- Only equi-joins are supported; no extra predicates, no expressions, no subqueries.
- Currently at most one matching row per stream record and dimension table is supported.
- Currently up to 4 dimension tables per
PIPEare supported. - Please refer to the Dimension table requirements section above for the requirements applicable to each dimension table.
See also¶
The Scenarios show real-world use cases that combine stream enrichment with other transformations. For the complete syntax with all features combined, see the Reference.
Previous: Stream filtering · Next: Custom scalar logic