# Modes

Here are the various loading modes available. All modes load into a new temporary table prior to final load.

<table data-full-width="false"><thead><tr><th width="212.60270475141198">Mode</th><th>Description</th></tr></thead><tbody><tr><td><code>full-refresh</code></td><td>This is the default mode. The target table will be dropped and recreated with the source data.</td></tr><tr><td><code>incremental</code></td><td>The source data will be merged or appended into the target table. If the table does not exist, it will be created. See below for more details.</td></tr><tr><td><code>truncate</code></td><td>Similar to <code>full-refresh</code>, except that the target table is truncated instead of dropped. This keeps any special DDL / GRANT applied.</td></tr><tr><td><code>snapshot</code></td><td>Appends the full dataset with an added timestamp column. If the target table exists, Sling will insert into / append data with a <code>_sling_loaded_at</code> column. If it does not, the table will be created.</td></tr><tr><td><code>backfill</code></td><td>Similar to <code>incremental</code>, but takes a <code>range</code> input to backfill a specific <code>update_key</code> range, such as dates or numbers.</td></tr><tr><td><code>definition-only</code></td><td>Creates the target table or file structure without transferring any data. For database targets, the table is created with the inferred schema but 0 rows. For file targets, only Parquet and Arrow formats are supported, creating a file with proper column types but no data rows.</td></tr><tr><td><code>change-capture</code></td><td>Captures row-level changes (inserts, updates, deletes) from the source database's transaction log. Performs an automatic initial snapshot on the first run, then reads incremental changes on subsequent runs. Requires a <code>primary_key</code>. See <a href="https://github.com/slingdata-io/sling-docs/blob/master/concepts/replication/change-capture.md">Change Capture (CDC)</a> for details.</td></tr></tbody></table>

### Incremental Mode Strategies

<table data-full-width="false"><thead><tr><th width="215.18644986449863">Load Strategy</th><th width="145" align="center">Primary Key</th><th width="160" align="center">Update Key</th><th>Stream Strategy</th></tr></thead><tbody><tr><td>New Data Upsert (update/insert)</td><td align="center"><code>yes</code></td><td align="center"><code>yes</code></td><td>Only new records after <code>max(update_key)</code></td></tr><tr><td>Full Data Upsert (update/insert)</td><td align="center"><code>yes</code></td><td align="center">no</td><td>Full data</td></tr><tr><td>Append Only (insert, no update)</td><td align="center">no</td><td align="center"><code>yes</code></td><td>Only new records after <code>max(update_key)</code></td></tr></tbody></table>

### Incremental or Backfill Mode With Custom SQL

When using `incremental` or `backfill` mode with a custom SQL stream, Sling provides two placeholder options to handle incremental loading:

* `{incremental_where_cond}`: Injects a complete WHERE condition
* `{incremental_value}`: Injects only the value, allowing for custom condition logic

#### Using {incremental\_where\_cond}

This placeholder injects a complete WHERE condition based on the `update_key`:

```sql
SELECT * FROM my_schema.my_table 
WHERE {incremental_where_cond}
```

Sling will replace the placeholder as follows:

* First run (table doesn't exist): `WHERE 1=1`
* Subsequent runs: `WHERE my_update_key > '[incremental_value]'`

For example, if the last maximum value was '2001-01-01 01:01:01', the query becomes:

```sql
SELECT * FROM my_schema.my_table 
WHERE my_update_key > '2001-01-01 01:01:01'
```

#### Using {incremental\_value}

This placeholder gives you more control over the WHERE condition by injecting only the value:

```sql
SELECT * FROM my_schema.my_table 
WHERE my_int_key > coalesce({incremental_value}, 0)  -- For numeric columns
-- or
WHERE my_timestamp > coalesce({incremental_value}, '2001-01-01')  -- For timestamp columns
```

Sling will replace the placeholder as follows:

* First run (table doesn't exist): `{incremental_value}` becomes `null`
* Subsequent runs: `{incremental_value}` becomes the last maximum value

For example, if the last maximum value was 99, the query becomes:

```sql
SELECT * FROM my_schema.my_table 
WHERE my_int_key > coalesce(99, 0)
```
