SSIS¶
This section describes the dbt output format for SSIS: how Data Flow Tasks are converted into dbt projects and Control Flow tasks and containers into Snowflake orchestration. For a before/after example of each Data Flow component, see Mappings and transformations.
The default conversion path is a dbt project. Eligible Data Flow graphs that connect a Flat File Source to an OLE DB Destination emit Direct COPY and do not create a dbt project. The --SimplifySsisDataFlows flag is not part of this dbt documentation series.
How a Data Flow becomes a dbt project¶
Each Data Flow Task is converted into a standalone dbt project with a three-tier model architecture.
| Layer | Materialization | Purpose |
|---|---|---|
models/staging/ | View | Clean, type-safe access to source data referenced in sources.yml. Generated from OLE DB Source, Flat File Source, ADO.NET Source, Excel Source, and Oracle Source. |
models/intermediate/ | Ephemeral by default | Transformation logic from the original Data Flow. Generated from Derived Column, Lookup, Aggregate, Conditional Split, and other transformations. Some components override that default: a Sort is materialized so its ORDER BY is preserved, and an OLE DB Command path can change the materialization of the models it feeds. |
models/marts/ | Table, incremental, or view | Business-ready data models that correspond to destinations. An OLE DB Destination, Excel Destination, Oracle Destination, or Flat File Destination becomes a mart named after the target. An OLE DB Command can produce an incremental model instead. |
Each Data Flow produces this project structure:
Important
Before deploying, replace the YOUR_SCHEMA and YOUR_DB placeholders in sources.yml and profiles.yml with your actual Snowflake schema and database names.
Most Data Flows follow the default path: the Data Flow becomes a dbt project, and the Control Flow Task that runs it calls EXECUTE DBT PROJECT. One case skips the dbt project. When a Data Flow only moves a Flat File Source into an OLE DB Destination, the conversion emits a Direct COPY instead: the Task runs a COPY INTO statement against the staged file, and no dbt project is generated for that Data Flow. Eligibility depends on the shape of the Data Flow, so check the generated output to see which path each Data Flow took. For the generated statements, see Mappings and transformations.
Data flow components¶
These SSIS Data Flow sources, transformations, and destinations are supported. Unlisted Data Flow components generate EWI SSC-EWI-SSIS0001. Raw File Source, Raw File Destination, and XML Source are not yet available. For a before/after example of each, see Mappings and transformations.
Control flow components¶
These SSIS Control Flow tasks and containers are supported:
Note: Unlisted Control Flow elements generate EWI SSC-EWI-SSIS0004.
Container Conversion Details¶
Sequence, For Loop, and ForEach containers are converted inline within the parent task or procedure. Event Handlers are converted to stored procedures; supported scoped handlers can be wired into the parent orchestration with CALL.
Sequence Containers¶
Sequence containers (https://learn.microsoft.com/en-us/sql/integration-services/control-flow/sequence-container?view=sql-server-ver17) are converted inline within the parent TASK. The container’s boundaries are marked with comments in the generated code, and all tasks within the container execute sequentially in the same TASK scope.
Conversion characteristics:
- No separate procedure or TASK is created for the container
- Container boundaries are clearly marked BEGIN … END blocks
- All tasks execute sequentially within the parent TASK
- Task execution order based on precedence constraints is maintained
- Limitation: Only “Success” precedence constraints are fully supported. Conditional execution based on task outcomes (Failure or Completion constraints) is not currently implemented and will require manual post-migration adjustments
Behavioral differences:
- FDM generated: SSC-FDM-SSIS0003
- Variable scoping differs from SSIS: Container variables are accessible throughout the entire parent TASK, not just within the container scope
Example:
For Loop Containers¶
For Loop containers (https://learn.microsoft.com/en-us/sql/integration-services/control-flow/for-loop-container?view=sql-server-ver17) convert to Snowflake Scripting WHILE loops when InitExpression, EvalExpression, and AssignExpression are present.
Conversion behavior¶
| Source | Snowflake | Notes |
|---|---|---|
| InitExpression | Assignment before the loop | Sets the loop counter |
| EvalExpression | WHILE condition | Loop continues while the condition is true |
| AssignExpression | Assignment at the end of the loop body | Increments or updates the counter |
| Missing Init/Eval/Assign | Body once + EWI | SSC-EWI-SSIS0004 |
Example¶
Limitations¶
- When Init, Eval, or Assign expressions are not present, the converted body runs once and SSC-EWI-SSIS0004 is generated.
ForEach Loop Containers¶
File Enumerator (Supported)
ForEach File Enumerator containers (https://learn.microsoft.com/en-us/sql/integration-services/control-flow/foreach-loop-container?view=sql-server-ver17) are converted to Snowflake stage operations using the LIST command and cursor pattern:
Configuration requirements:
After migration, you’ll need to:
- Replace
<STAGE_PLACEHOLDER>with your actual Snowflake stage name - Ensure the folder path is correctly mapped to a Snowflake stage
- Verify that files are properly staged in Snowflake
An EWI (SSC-EWI-SSIS0014) is generated to remind you of this manual configuration step.
ADO enumerator
ForEach ADO enumerators emit a cursor plus per-row variable assignments. The cursor source is a placeholder SELECT null until you replace it with the upstream result-set query. That placeholder emits SSC-EWI-SSIS0004. This is not a LIST pattern.
Conversion behavior¶
| Source | Snowflake | Notes |
|---|---|---|
| ADO enumerator | Cursor over a query | Replace SELECT null with the query that populated the recordset |
| Column mappings | Variable assignments inside FOR | Each mapped column is assigned and persisted with UpdateControlVariable |
Example¶
Limitations¶
- SSC-EWI-SSIS0004. Replace
SELECT nullwith the upstream result-set query before running the task.
From Variable enumerator
ForEach From Variable enumerators flatten a collection variable and iterate with RESULT_SCAN, not LIST.
Conversion behavior¶
| Source | Snowflake | Notes |
|---|---|---|
| Collection variable | TABLE(FLATTEN(...)) | One row per collection element |
| Cursor | RESULT_SCAN(LAST_QUERY_ID()) | Feeds the FOR loop |
| Mapped variable | Assignment from VALUE | Updated with UpdateControlVariable |
Example¶
Other enumerator types
ForEach Item, NodeList, SMO, HDFS, and SchemaRowset enumerators are not yet available. An EWI (SSC-EWI-SSIS0004) is generated for these cases.
Event Handlers¶
Event handlers (https://learn.microsoft.com/en-us/sql/integration-services/integration-services-ssis-event-handlers?view=sql-server-ver17) are converted to stored procedures. Supported scoped OnPreExecute and OnPostExecute handlers can be CALL-wired from the converted orchestration. Package-level handlers and OnError or OnWarning procedures can remain untriggered.
Conversion behavior¶
| Source | Snowflake | Notes |
|---|---|---|
| Scoped OnPreExecute / OnPostExecute | Stored procedure + CALL | Wired around the converted task or container |
| OnError / OnWarning | Stored procedure | Can remain untriggered |
| Package-level handlers | Stored procedure | Can remain untriggered |
Example¶
Limitations¶
- OnError, OnWarning, and package-level handler procedures can remain untriggered and require manual invocation or a triggering mechanism. See SSC-FDM-SSIS0006.
Execute SQL Task¶
Execute SQL Tasks (https://learn.microsoft.com/en-us/sql/integration-services/control-flow/execute-sql-task?view=sql-server-ver17) are converted as inline SQL statements or separate stored procedures, depending on complexity and result set bindings.
Conversion approach:
- Simple SQL statements: Converted inline within the parent TASK
- Complex statements with result sets: May be converted to separate stored procedures
- Result bindings: Handled where possible; unsupported patterns generate EWI SSC-EWI-SSIS0011
Execute Package Task¶
Execute Package Tasks (https://learn.microsoft.com/en-us/sql/integration-services/control-flow/execute-package-task?view=sql-server-ver17) are handled differently based on package type:
| Package Type | Conversion | Notes |
|---|---|---|
| Local (single reference) | Inline execution within parent TASK | Package logic expanded inline |
| Reusable (2+ references or parameters) | CALL to stored procedure | Enables synchronous execution with parameters; generates FDM SSC-FDM-SSIS0005 |
| External | CALL with path resolution | Generates EWI SSC-EWI-SSIS0008 for manual verification |
Asynchronous execution note:
TASK-based Execute Package conversions run asynchronously. For synchronous behavior, packages are converted to stored procedures. See EWI SSC-EWI-SSIS0005.
File System Task¶
File System Tasks (https://learn.microsoft.com/en-us/sql/integration-services/control-flow/file-system-task?view=sql-server-ver17) convert to Snowflake stage operations (COPY FILES and REMOVE). They do not become dbt models.
Conversion behavior¶
| Source operation | Snowflake | Notes |
|---|---|---|
| Copy | COPY FILES INTO ... FROM ... | Destination is treated as a directory prefix |
| Move | COPY FILES then REMOVE | Removes the source after copy |
| Delete directory content | REMOVE then a .keep COPY INTO | Prefix-based stage paths |
Example¶
Limitations¶
- Destination paths are directory prefixes (SSC-EWI-SSIS0044).
- Snowflake stages use prefix-based paths rather than real directories, so
REMOVEwith a trailing slash deletes every file matching the prefix (SSC-FDM-SSIS0028). - Variable values must contain a valid Snowflake stage path (SSC-FDM-SSIS0025).
Expression Task¶
Expression Tasks (https://learn.microsoft.com/en-us/sql/integration-services/control-flow/expression-task?view=sql-server-ver17) convert SSIS expressions to Snowflake Scripting assignments (:=). They do not become dbt models.
Conversion behavior¶
| Source | Snowflake | Notes |
|---|---|---|
| Expression Task | variable := <converted expression> | Functions such as UPPER are rewritten to Snowflake |
Example¶
Send Mail Task¶
Send Mail Tasks (https://learn.microsoft.com/en-us/sql/integration-services/control-flow/send-mail-task?view=sql-server-ver17) are converted to Snowflake Tasks that use SYSTEM$SEND_EMAIL with a dynamically created Notification Integration.
Conversion behavior¶
| Aspect | SSIS | Snowflake |
|---|---|---|
| Email Service | Custom SMTP server | Snowflake’s built-in email service |
| Configuration | SMTP Connection Manager | Notification Integration |
| Sender Address | Custom FROM address | Fixed by Snowflake account |
| CC/BCC Support | Full support | Not supported (merged into recipients) |
| Attachments | File attachments supported | Not supported |
| HTML Body | Supported | Plain text only |
| Priority | High/Normal/Low | Not supported |
Property mapping¶
| SSIS Property | Snowflake Equivalent | Notes |
|---|---|---|
| ToLine | ALLOWED_RECIPIENTS + recipients parameter | Direct mapping |
| FromLine | Prepended to message body | FDM SSC-FDM-SSIS0008 |
| CCLine | Added to recipients list | FDM SSC-FDM-SSIS0009 |
| BCCLine | Added to recipients list | FDM SSC-FDM-SSIS0010 (privacy concern) |
| Subject | subject parameter | Direct mapping |
| MessageSource | message parameter | Direct mapping |
| MessageSourceType (DirectInput) | Supported | - |
| MessageSourceType (Variable) | Supported | Variable reference converted |
| MessageSourceType (FileConnection) | Not supported | EWI SSC-EWI-SSIS0017 |
| Priority | Not supported | EWI SSC-EWI-SSIS0016 |
| FileAttachments | Not supported | EWI SSC-EWI-SSIS0015 |
| SMTPConnection | Managed by Snowflake | FDM SSC-FDM-SSIS0007 |
| BodyFormat (HTML) | Not supported | EWI SSC-EWI-SSIS0018 |
Example¶
Each Send Mail Task is converted to a Snowflake Task containing:
- Notification Integration Creation: Created dynamically via
EXECUTE IMMEDIATE - SYSTEM$SEND_EMAIL Call: Sends the email through the integration
Basic Email (To, Subject, Body):
Email with FROM Address:
Email with Multiple Features (attachments, priority, CC):
Prerequisites for Snowflake Email¶
Before using converted Send Mail Tasks:
- Email Notification Integration permissions: Account admin must grant
CREATE INTEGRATION ON ACCOUNTto the executing role - Recipient verification: All email addresses in
ALLOWED_RECIPIENTSmust be verified in Snowflake - Update warehouse name: Replace
DUMMY_WAREHOUSEwith your actual warehouse name
Limitations¶
File Attachments:
Upload files to a Snowflake stage and share links instead:
BCC Privacy:
Send separate emails to maintain recipient privacy:
Bulk Insert Task¶
Bulk Insert Tasks (https://learn.microsoft.com/en-us/sql/integration-services/control-flow/bulk-insert-task?view=sql-server-ver17) are converted to Snowflake Tasks that use COPY INTO with an inline FILE_FORMAT. The conversion generates a stage placeholder that you must configure before execution.
Conversion behavior¶
| Aspect | SSIS | Snowflake |
|---|---|---|
| Data Source | File system path or UNC path | Snowflake Stage (internal or external) |
| File Format | Format file (.fmt/.xml) or inline options | FILE_FORMAT object or inline options |
| Native Format | Native/WideNative supported | Not supported (CSV, JSON, Parquet, etc.) |
| Row Filtering | FirstRow/LastRow options | Not directly supported |
| Batch Control | BatchSize configurable | Automatic management |
| Error Handling | MaximumErrors count | ON_ERROR behavior |
| Triggers | FireTriggers option | Not supported (use Streams/Tasks) |
| Table Locking | TableLock option | Not needed (MVCC) |
Property mapping¶
| SSIS Property | Snowflake Equivalent | Notes |
|---|---|---|
| DestinationTableName | COPY INTO table | Square brackets [] removed |
| DataFileType (Char) | TYPE = 'CSV' | Direct mapping |
| DataFileType (Native) | Not supported | EWI SSC-EWI-SSIS0020 |
| FieldTerminator | FIELD_DELIMITER | Parsed from SSIS format |
| RowTerminator | RECORD_DELIMITER | Parsed from SSIS format |
| FirstRow | SKIP_HEADER | Value - 1 |
| LastRow | Not supported | EWI SSC-EWI-SSIS0021 |
| MaximumErrors | ON_ERROR | FDM SSC-FDM-SSIS0011 |
| KeepNulls=True | NULL_IF = () | Empty tuple |
| KeepNulls=False | NULL_IF = ('', 'NULL', 'null') | Default behavior |
| KeepIdentity=False | FDM generated | FDM SSC-FDM-SSIS0017 |
| TableLock=True | Not needed | FDM SSC-FDM-SSIS0014 |
| FireTriggers=True | Not supported | EWI SSC-EWI-SSIS0022 |
| FormatFile | Not supported | EWI SSC-EWI-SSIS0023 |
| CheckConstraints=True | Always enforced | FDM SSC-FDM-SSIS0016 |
| BatchSize | Automatic | FDM SSC-FDM-SSIS0012 |
| SortedData | Not available | FDM SSC-FDM-SSIS0015 |
Terminator Parsing¶
SSIS uses specific tokens for field and row terminators. These are converted to Snowflake escape sequences:
| SSIS Format | Snowflake Output |
|---|---|
{CR}{LF} | \r\n |
{CR} | \r |
{LF} | \n |
{TAB} | \t |
Tab | \t |
Comma {,} | , |
Semicolon {;} | ; |
Vertical Bar {|} | | |
Example¶
Each Bulk Insert Task is converted to a Snowflake Task containing a COPY INTO statement with an inline FILE_FORMAT:
Basic Bulk Insert (CSV with default options):
Bulk Insert with Tab Delimiter and Header Skip:
Bulk Insert with Multiple EWIs (Native format, LastRow, FireTriggers):
Stage Setup (Required)¶
Before executing converted Bulk Insert Tasks, you must:
- Create a Snowflake stage:
- Upload files using SnowSQL CLI:
- Replace the stage placeholder in generated code:
- Verify files are staged:
Limitations¶
Native Data Format:
Export SQL Server data to CSV format before migration. The native binary format is not supported by Snowflake.
LastRow Filtering:
Load to staging table and filter:
FireTriggers (Trigger-like Behavior):
Use Snowflake Streams and Tasks:
dbt Project Execution¶
Within the orchestration code, Data Flow Tasks are executed using Snowflake’s EXECUTE DBT PROJECT command:
Important requirements:
- The
project_namemust match the name you used when deploying the dbt project (viaCREATE DBT PROJECTor Snowflake Workspace deployment) - Arguments passed are standard dbt CLI arguments (like
build,run,test) - Each execution runs the entire dbt project with all models in dependency order
Deployment:
Before executing dbt projects in orchestration, deploy them using:
- Snowflake CLI:
snow dbt deploy --schema schema_name --database database_name package_name - Snowflake Workspace: Upload and deploy via UI