Columns
Selecting Columns
Use the select option to narrow a stream down to the columns you actually need. Replication is read-once, write-once, so dropping unused columns shrinks the bytes transferred, the storage footprint at the target, and the time spent inferring/casting types.
From v1.5.19+,select works on every source: databases (where it becomes SELECT col1, col2, ...), file sources (CSV, JSON, JSONL, Parquet), and API sources. Three things make up the grammar:
Exact names to include (
id,email)Glob patterns to include or exclude (
user_*,*_at,-internal_*)Renames with the
askeyword (id as user_id)
Using CLI Flags
# include specific columns
sling run --select 'id,email,created_at'
# include everything except a few (minus prefix is the exclude marker)
sling run --select '-password,-ssn'
# include with a glob; here, only columns named like `event_*`
sling run --select 'event_*'
# rename inline
sling run --select 'id as user_id,name as full_name'Using YAML
Picking a Subset
The most common use of select is to whittle a wide source table down to the columns the target actually needs. Two shapes show up most often:
1. Include exactly what you want. Everything not listed is dropped.
2. Include everything except a few. Use - prefixes. When every item is an exclusion, Sling treats it as "select all except these."
You cannot mix exact include names with - exclusions in the same list — pick one shape per stream.
Globs
Globs let one pattern match many columns. They work in both include lists and exclude lists.
Supported patterns: prefix (prefix_*), suffix (*_suffix), contains (*middle*), and exact names. Matching is case-insensitive.
Renaming
The as keyword renames columns on the way out. For database sources this generates SELECT column AS alias directly; for file and API sources Sling rewrites the column header after read. Renames sit alongside includes — list anything you don't rename as-is. Requires v1.5.5+.
When using custom SQL with the {fields} placeholder, the renamed columns are substituted automatically:
Controlling Column Order
The order of items in the select list is the order columns appear in the target. This matters when you're writing to a file (CSV, Parquet, JSON) where readers care about column order, or when you want a stable layout regardless of how the source happens to list its columns.
You can pin specific columns to the front, let the rest follow in source order via *, and pin others to the back:
* expands to whatever's left after the pins are accounted for, in the order the source declared the columns. Globs can also be used as pins ('user_*' between two exact pins drops every matching column there in source order).
If you don't need reordering, just leave * out — Sling preserves source order by default.
Reusing columns for Order
columns for OrderWhen you've already listed your columns under columns to pin their types, you don't have to repeat every name under select just to control order. From v1.5.20+, the @columns token expands to the names declared in columns, in that declared order.
@columns must be the first item in the select list. Use it alone to emit exactly the declared columns, or follow it with * to pin the declared columns first and let the rest follow.
Notes:
@columnsis only honored as the first item — using it anywhere else is an error.It requires a
columnsblock on the stream (after merging with defaults); using it with no columns defined is an error.Names that would be duplicated by the expansion are kept once (first occurrence wins), so
['@columns', 'id']won't listidtwice.
Casting Columns
When running a replication, you can specify the column types to tell Sling to cast the data to the correct type. It is not necessary to include all columns. Sling will automatically detect the types for any unspecified columns. See here and here for various type mappings between native and generic types for all types of databases.
Acceptable data types are:
bigintbooldatetimedecimalordecimal(precision, scale)(such asdecimal(10, 2))integerjsonstringorstring(length)(such asstring(100))textortext(length)(such astext(3000))geometry
Sling allows you the ability to apply constraints, such as value > 0. See Constraints for details.
Column Modifiers
From v1.5.20+, the type slot accepts space-separated modifiers after the data type. These shape the DDL Sling generates when it creates the target table — adding NOT NULL, primary keys, unique constraints, column descriptions, and indexes — without having to hand-write table_ddl. They apply on a fresh CREATE TABLE regardless of any schema-migration setting.
The first token is always the type; everything after it is a modifier. The supported modifiers are:
not_null
Column is NOT NULL.
nullable
Column is explicitly nullable (the default; useful to override a source-derived not_null).
primary_key
Column is part of the table's PRIMARY KEY (DDL only — does not set the incremental-mode primary key; use primary_key / table_keys.primary for that).
unique
Adds a UNIQUE constraint on the column.
index
Creates a plain index on the column.
index(...)
Creates a plain index with options (see kwargs below).
unique_index / unique_index(...)
Creates a unique index on the column.
description('<text>')
Sets the column comment/description. A user-supplied description wins over one inferred from the source.
The index(...) / unique_index(...) forms accept keyword arguments to compose multi-column or partial indexes across several columns. Give the same name to two columns to build a composite index, and use priority to order the members:
Supported kwargs: name, priority, sort (asc/desc), where, type, include. See also table_keys.index options for defining composite indexes.
Whether each modifier renders depends on the target engine. For example, ClickHouse honors not_null (columns are not wrapped in Nullable(...)) and renders indexes inline, while engines without secondary indexes (Snowflake, Redshift) silently ignore index. Index and description statements are only applied to the final table, never the transient staging table.
The runtime constraint slot (after |) is unaffected and can be combined with modifiers:
Using CLI Flags
Using YAML
Using the defaults and streams keys, you can specify different columns for each stream.
Merging with Defaults
By default, stream-level columns replace defaults.columns entirely. To merge stream columns with defaults instead, prefix column names with +. This inherits all defaults and lets you add or override specific columns. Requires v1.5.12+.
You cannot mix + prefixed and non-prefixed column names in the same columns block. Either all columns use the + prefix (merge mode) or none do (replace mode).
Unsetting a Default
When using merge mode (+ prefix), you can remove a default column type for a specific stream by setting it to null using YAML's ~. This reverts that column to the auto-detected type from the source.
Column Casing
The column_casing target option allows you to control how column names are formatted when creating tables in the target database. This is useful for ensuring consistent naming conventions and avoiding the need to use quotes when querying tables in databases with case-sensitive identifiers.
Starting in v1.4.5, the default is normalize. Before this version, the default was source. See note here for details.
Available Casing Options
normalize- Normalize column names to target database's default casing (upper or lower case), but preserve mixed-case column names. This helps with querying tables without needing quotes for standard column names.source- Keep the original casing from the source data.target- Convert all column names according to the target database's default casing (upper case for Oracle, lower case for PostgreSQL, etc.).snake- ConvertcamelCaseand other formats tosnake_case, then apply the target database's default casing.upper- Convert all column names to UPPER CASE.lower- Convert all column names to lower case.
Examples
Assuming source column names: customerId, first_name, LAST_NAME, email-address
Using CLI Flag
Using YAML
Example Results
Let's see how each option transforms our sample column names for a PostgreSQL, DuckDB or MySQL target (which defaults to lowercase):
customerId
customerId
customerId
customerid
customer_id
CUSTOMERID
customerid
first_name
first_name
first_name
first_name
first_name
FIRST_NAME
first_name
LAST_NAME
LAST_NAME
last_name
last_name
last_name
LAST_NAME
last_name
email-address
email-address
email-address
email_address
email_address
EMAIL_ADDRESS
email_address
For an Oracle or Snowflake target (which defaults to uppercase):
customerId
customerId
customerId
CUSTOMERID
CUSTOMER_ID
CUSTOMERID
customerid
first_name
first_name
FIRST_NAME
FIRST_NAME
FIRST_NAME
FIRST_NAME
first_name
LAST_NAME
LAST_NAME
LAST_NAME
LAST_NAME
LAST_NAME
LAST_NAME
last_name
email-address
email-address
email-address
EMAIL_ADDRESS
EMAIL_ADDRESS
EMAIL_ADDRESS
email_address
This functionality makes it easier to work with column names when moving data between systems with different naming conventions or case sensitivity requirements.
Column Typing
Starting in v1.4.5, the column_typing target option allows you to configure how Sling generates column types when creating tables in the target database. This is particularly useful when you need to ensure string columns have sufficient length to accommodate all possible values, especially when dealing with different database systems or character encodings.
Structure
The column_typing configuration has the following structure:
Where:
string: Settings for string type columnslength_factor: A multiplier applied to the detected length of string columns (default: 1)min_length: The minimum length to use for string columns (if specified)max_length: The maximum length to use for string columns (if specified)use_max: Whether to always use the max_length value instead of calculated lengths (default: false)
decimal: Settings for decimal type columnsmin_precision: The minimum total number of digits (precision) for decimal columns.max_precision: The maximum total number of digits (precision) for decimal columns.min_scale: The minimum number of digits after the decimal point (scale).max_scale: The maximum number of digits after the decimal point (scale).cast_as: Force decimal columns to be cast as a specific type (available inv1.4.27+):"float": Convert decimal columns to floating-point type (e.g.,DOUBLE PRECISIONin PostgreSQL)"string": Convert decimal columns to string/text type (e.g.,VARCHARin PostgreSQL)
json: Settings for JSON type columnsas_text: When set totrue, JSON columns are stored as text/string type instead of native JSON type (default: false). This is useful when the target database doesn't support native JSON types, or when you need to store JSON data as plain text for compatibility.
boolean: Settings for boolean type columnscast_as: Force boolean columns to be cast as a specific type:"integer": Convert boolean columns to integer type (1 for true, 0 for false)"string": Convert boolean columns to string type ("true" or "false")
How It Works
When Sling creates tables in the target database, it analyzes the source data to determine appropriate column types.
For string columns:
Sling determines the maximum string length from the source data
If
length_factoris specified, this value is multiplied by the factorIf
max_lengthis specified anduse_maxis false, the length is capped at this valueIf
use_maxis true,max_lengthis used regardless of the calculated lengthIf
min_lengthis specified, the length will be at least that number
For decimal columns:
Sling determines the required precision and scale based on the source data.
If
cast_asis specified:"float": Decimal columns are converted to floating-point type, ignoring precision/scale settings"string": Decimal columns are converted to string/text type, preserving exact decimal representation
Otherwise, if
column_typing.decimalsettings are provided, Sling adjusts the calculated precision and scale based on themin_precision,max_precision,min_scale, andmax_scalevalues.The final precision and scale are used to generate the
decimal(precision, scale)type in the target database DDL.
This helps prevent truncation issues when moving data between systems with different character encoding requirements or different decimal precision/scale needs.
Examples
Double String Column Lengths
In this example, all string columns in the dbo.test_sling_unicode table will have their length doubled when created in the PostgreSQL target. This is useful when moving from a database that uses single-byte encoding to one that uses multi-byte encoding (like UTF-8).
Set Maximum String Length
This example sets a maximum length of 8000 characters for all string columns across all streams, which is useful for databases with column size limitations.
Use Fixed String Length
This configuration forces all string columns in the sales.customers table to use a fixed length of 1000, regardless of the actual data length.
Cast Decimals as Float
This example converts all decimal columns to floating-point type (DOUBLE PRECISION in PostgreSQL). This is useful when you need better performance for numeric operations and can accept the loss of exact decimal precision.
Cast Decimals as String
This example converts all decimal columns to string type (VARCHAR in PostgreSQL). This is useful when you need to preserve exact decimal representation, including trailing zeros, or when the target database doesn't support the required decimal precision.
Store JSON as Text
This example stores JSON columns as text instead of native JSON type. This is useful when replicating to databases that don't have native JSON support, or when you want to store JSON data as plain text for compatibility with older systems or specific application requirements.
Cast Booleans as Integer
This example converts boolean columns to integer type (1 for true, 0 for false). This is useful when replicating to databases that don't have native boolean support, such as Oracle, or when integrating with legacy systems that expect numeric flags. Available in v1.5.3+.
Cast Booleans as String
This example converts boolean columns to string type ("true" or "false"). This can be useful for data warehousing scenarios where you want boolean values stored as human-readable text, or when the target system expects string representations of boolean values.
Last updated
Was this helpful?