In-flight processing
Output and computed columns
Choose which columns a target receives, add computed columns with worked examples, and see how SQL Flow types them on the target.
By default a target receives every source column. Choose output columns replaces that with a list you control: you keep some source columns, add computed ones, and every column you don't list is dropped.
Before you begin
- Know the table's primary key, unique keys and foreign keys. Those columns must stay in the list unchanged.
- See Validation and limits for the source settings that rules need.
Choose the output columns of one table
- Open Configure for the target and select the table.
- Tick Choose output columns.
- For each source column to keep, type its name in Source column to keep and select Keep source column. The column is added with its quoted name as the expression, such as
"id". - To add a computed column, select Add computed column, then enter an Output name and a Source expression.
- Select Remove beside any column you don't want.
- Select Done in the wizard, or Save and reload… on an existing pipeline.
List every column to keep, including all source key columns. A source column that isn't listed isn't created at the target.
| Output name | Source expression | Result |
|---|---|---|
id | id | Keeps the key column unchanged. |
amount | CAST(amount AS DECIMAL(18,2)) | Keeps amount with a new type. |
email | PARTIAL_MASK(email, 1, 3) | Keeps email, masked. See Masking. |
full_name | CONCAT(CONCAT(first_name, ' '), last_name) | Adds a computed column. |
size_band | CASE WHEN quantity >= 100 THEN 'bulk' ELSE 'retail' END | Adds a computed column. |
Expressions always read the original source values, never another output column. Only the operators and functions in the Expression reference are accepted: CONVERT, TRY_CAST, ISNULL, LEN, SUBSTRING and YEAR, for example, are refused before the start. See Expression errors for every code.
Examples
The examples are written in T-SQL for a SQL Server source and use a table dbo.Orders with these columns:
| Column | Type |
|---|---|
order_id | int, primary key |
first_name | nvarchar(50) |
last_name, nickname | nvarchar(50), nullable |
email | nvarchar(255), nullable |
status_code | char(1) |
country_code | char(2) |
quantity | int |
unit_price | decimal(10,2) |
discount | decimal(10,2), nullable |
amount_text | varchar(20) |
promised_text | varchar(30) |
ordered_at, promised_at | datetime2 |
shipped_at | datetime2, nullable |
Each example gives the Output name and the Source expression to enter. Keep order_id in the list as well, because it is the key.
Join text
CONCAT joins exactly two text values, so nest it to join more. The result is NULL when either value is NULL; wrap it in COALESCE to fall back to another value. Cast a number to text before joining it.
| Output name | Source expression |
|---|---|
full_name | CONCAT(CONCAT(first_name, ' '), last_name) |
full_name | COALESCE(CONCAT(CONCAT(first_name, ' '), last_name), first_name) |
order_ref | CONCAT('ORD-', CAST(order_id AS VARCHAR(11))), such as ORD-1001 |
first_name | last_name | First expression | With COALESCE |
|---|---|---|---|
Ada | Lovelace | Ada Lovelace | Ada Lovelace |
Grace | NULL | NULL | Grace |
In T-SQL, + adds numbers only: first_name + ' ' + last_name is refused with numeric-type. On a source whose dialect has the || operator, such as Oracle, first_name || ' ' || last_name works like the nested CONCAT.
Clean up text
| Output name | Source expression | Value | Result |
|---|---|---|---|
email | LOWER(TRIM(email)) | ' Ada@Example.com' | 'ada@example.com' |
country_code | UPPER(country_code) | 'de' | 'DE' |
TRIM removes leading and trailing spaces only, not tabs or line breaks.
Calculate amounts
+, - and * compute exact numbers and never round:
| Output name | Source expression | Values | Result |
|---|---|---|---|
line_total | quantity * unit_price | 12, 9.99 | 119.88 |
net_price | unit_price - COALESCE(discount, 0) | 9.99, NULL | 9.99 |
price_with_tax | unit_price * 1.2 | 9.99 | 11.988 |
line_total is created as decimal(38, 2). To choose the type, cast the result, for example CAST(quantity * unit_price AS DECIMAL(18,2)).
A cast never rounds, so a value with too many decimal places stops the pipeline. CAST(unit_price * 1.2 AS DECIMAL(18,2)) works for 10.00 (12.000) and stops with numeric-overflow-or-rounding for 9.99 (11.988). There is no division and no rounding function: unit_price / 2 is refused with unsupported-operator.
Label rows with CASE
A searched CASE tests conditions in order and returns the first match. A NULL condition counts as false, so a NULL quantity gets unit here:
| Output name | Source expression |
|---|---|
size_band | CASE WHEN quantity >= 100 THEN 'bulk' WHEN quantity >= 10 THEN 'case' ELSE 'unit' END |
A simple CASE compares one value with each WHEN:
| Output name | Source expression |
|---|---|
status_label | CASE status_code WHEN 'A' THEN 'active' WHEN 'C' THEN 'closed' ELSE 'unknown' END |
Without ELSE, a row that matches no WHEN gets NULL, and the column is nullable.
Replace missing values
COALESCE returns its first value that isn't NULL:
| Output name | Source expression | Values | Result |
|---|---|---|---|
display_name | COALESCE(nickname, first_name) | NULL, 'Grace' | 'Grace' |
discount | CAST(COALESCE(discount, 0) AS DECIMAL(10,2)) | NULL | 0.00 |
COALESCE(discount, 0) alone becomes decimal(38, 2); the cast keeps the source's decimal(10,2). Use COALESCE, not ISNULL or NVL, which are refused.
Derive flags
A comparison, an IN list or a NULL check produces a Boolean column, created as bit:
| Output name | Source expression | Result |
|---|---|---|
is_large_order | quantity * unit_price >= 1000 | 1 when the order is worth 1,000 or more |
has_email | email IS NOT NULL | 1 or 0, never NULL |
is_domestic | country_code IN ('US', 'CA') | 1 for US and Canadian orders |
A flag is NULL when a value it compares is NULL, except for IS NULL and IS NOT NULL.
Change a type
| Output name | Source expression | Value | Result |
|---|---|---|---|
unit_price | CAST(unit_price AS DECIMAL(18,4)) | 9.99 | 9.9900 |
order_ref | CAST(order_id AS VARCHAR(11)) | 1001 | '1001' |
amount | CAST(TRIM(amount_text) AS DECIMAL(12,2)) | ' 42.50 ' | 42.50 |
ordered_text | CAST(ordered_at AS VARCHAR(33)) | 1 May 2024, 13:45 | '2024-05-01T13:45:00.0000000' |
promise_time | CAST(promised_text AS DATETIME2) | '2024-05-03T00:00:00.0000000' | 3 May 2024, 00:00 |
Text converts only from exact forms: '1,200.00' stops CAST(amount_text AS DECIMAL(12,2)) with invalid-number, and '2024-05-03' stops a cast to DATETIME2 with datetime-cast. See Casts for every conversion.
Work with dates and times
There are no date functions: YEAR(ordered_at) is refused, and so is CAST(ordered_at AS DATE). You can keep a date column, cast it to text or to another date and time type of the same kind, test it for NULL, and compare it with another value of the same kind:
| Output name | Source expression |
|---|---|
delivery_state | CASE WHEN shipped_at IS NULL THEN 'open' WHEN shipped_at > promised_at THEN 'late' ELSE 'on time' END |
is_shipped | shipped_at IS NOT NULL |
last_event_at | COALESCE(shipped_at, ordered_at) |
Add a constant column
A constant column has the same value in every row, for example to tag rows with their origin:
| Output name | Source expression | Result |
|---|---|---|
source_region | CAST('eu-west' AS VARCHAR(16)) | 'eu-west', as varchar(16) |
legacy_code | CAST(NULL AS VARCHAR(10)) | NULL, as a nullable varchar(10) |
A NULL needs a cast to give the column a type: a bare NULL is refused with invalid-output-facets.
Columns that must pass through unchanged
These columns must be in the list as a plain column reference, with the output name equal to the source column name:
- every primary key column;
- every column of a unique index;
- every column of a foreign key, on either side of the relationship.
SQL Flow writes and deletes target rows by key, so these values can't be computed, masked or renamed by the rule. To give such a column another name at the target, use Column names in the same dialog. A missing or changed key column is refused with protected-column-missing-or-transformed, and a renamed one with protected-column-alias.
For the key order_id:
| Output name | Source expression | Result |
|---|---|---|
order_id | order_id | Accepted. |
id | order_id | Refused with protected-column-alias. Rename it with Column names instead. |
order_id | CAST(order_id AS BIGINT) | Refused with protected-column-missing-or-transformed. |
A computed column can still read a key, as order_ref does above, as long as the key itself is also in the list unchanged.
Output columns for all tables
Under All tables, open Output columns and masks for all tables (optional) and tick Choose global output columns. The list is a template: it applies to each table that has every column its expressions name. Other tables keep all their columns. A table that chooses its own output columns ignores the template and the global masks.
For example, when every table you want to trim has the key id and the columns email and updated_at, this template keeps only those three columns in each of them, with email in lowercase:
| Output name | Source expression |
|---|---|
id | id |
email | LOWER(email) |
updated_at | updated_at |
The template is a complete list, so it drops every other column of the tables it applies to. A table with these columns whose key isn't id is refused with protected-column-missing-or-transformed; give that table its own list. To change a few columns and keep the rest, use global masks instead.
Names at the target
The Output name names the column in the rule. The table's Column names then rename it at the target, the same way they rename a source column. Output names must be unique within a table, ignoring case, after the renames are applied (output-name-collision). For example, the outputs Email and email collide.
How computed columns are typed
Prepare target schema creates the target table with the output columns. A kept source column keeps its source type and is mapped to the target like any other column. A computed column takes the type of its expression:
| Expression | Column type before mapping to the target |
|---|---|
+, - or * on numbers | decimal(38, s), where s is the larger scale for + and -, and the sum of the scales for * |
| A number literal | decimal(38, s), with the literal's scale |
CAST(x AS <type>) | The cast type, for example decimal(18,2) or varchar(32) |
Text literal, CONCAT, LOWER, UPPER, TRIM, PARTIAL_MASK | nvarchar(n), where n is the longest result the inputs allow |
HASH_MASK | varchar(64) |
Comparisons, IN, IS NULL, AND, OR, NOT | bit |
CASE, COALESCE | The common type of the branches |
VECTOR_DISTANCE, VECTOR_NORM | float |
For example, full_name above (CONCAT of two nvarchar(50) columns and ' ') is nvarchar(101), and price_with_tax is decimal(38, 3). A computed text column that can be longer than 4,000 characters (nvarchar) or 8,000 characters (varchar) becomes nvarchar(max). On SQL Server targets, computed text columns use the binary collation Latin1_General_100_BIN2.
A computed column is nullable when any of its inputs is nullable. COALESCE is nullable only when all its arguments are.
Large values
A large-object column, such as nvarchar(max) or varbinary(max), can be kept as a plain column reference whatever its size. Inside an expression:
- Values up to 1 MiB work with every operation.
- Larger values work with
HASH_MASK,PARTIAL_MASK,CONCAT,LOWER,UPPER,TRIM,COALESCE,CASE, comparisons,IS NULL,AND,ORandNOT. Any other operation on such a value stops the pipeline withprocessing_lob_stream_operation_unsupported.
The same large-object column can't be listed twice (processing_lob_duplicate_output_unsupported), and it can't be a key (processing_lob_key_unsupported). See Large values and LOBs.
A computed text column that becomes nvarchar(max) needs a large-object column among its inputs. For example, CONCAT of two nvarchar(4000) columns can reach 8,000 characters without one, so it is refused with processing-computed-output-requires-lob.
Computed columns on the source
An expression can read a computed source column when the column is numeric (not money or smallmoney) and its definition uses only numeric arithmetic, CAST, CONVERT with no style or style 0, and COALESCE. Other computed columns are refused when a rule reads them, for example with processing_derived_source_unsupported or generated-function-unproved.
