SCD Type 2 SQL Generator
Slowly changing dimension Type 2 tracking is easy to describe and easy to get subtly wrong — a missed NULL comparison, a MERGE that closes a row but never inserts its replacement, or two current rows for one business key. This generator writes the whole pattern for you: the dimension DDL with surrogate key, validity range and is_current flag, the optional row hash used for change detection, and the load logic in both the safe two-step form and the single MERGE form. Pick PostgreSQL, Snowflake or BigQuery and the syntax adapts. Everything runs in your browser; nothing is uploaded.
Do more than scd type 2 sql generator — meet Chat2DB
Chat2DB is an AI-powered SQL client for Windows, macOS and Linux. Write SQL in natural language, format and optimize queries automatically, and manage MySQL, PostgreSQL, Oracle and 20+ other databases in one workspace.
How to use
- Enter the dimension table, the staging table holding the incoming snapshot, and the business (natural) key column.
- List the attributes whose changes should create a new version, and choose your SQL dialect.
- Copy the generated DDL and the load SQL, and read the notes for the NULL, transaction and deduplication pitfalls.
Frequently asked questions
What is a slowly changing dimension Type 2?
A Type 2 dimension keeps history by adding a new row each time a tracked attribute changes, instead of overwriting the old value. Each row carries a surrogate key, the business key, a validity range (valid_from / valid_to) and an is_current flag. Facts join to the surrogate key that was current when the event happened, so a sales report from last year still shows the customer's segment as it was then. Type 1 simply overwrites and keeps no history; Type 3 stores only a single 'previous value' column.
Should I use a row hash or compare columns to detect changes?
A row hash (MD5 over the concatenated tracked attributes) is one equality check no matter how many columns you track, which keeps the load SQL short and makes adding a column a one-line edit. Compare columns individually when you need to know which attribute changed, or when the warehouse charges for the hash computation over very wide rows. If you do compare columns, use IS DISTINCT FROM rather than <>: plain <> returns NULL when either side is NULL, so a value changing to or from NULL would never be detected.
Why does a single MERGE statement not fully implement SCD Type 2?
Because MERGE acts at most once per matched target row. Closing the old version is an UPDATE on the matched row, and inserting the new version is a second action on the same source row — most engines will not do both. The reliable pattern is two statements in one transaction: UPDATE the current rows that changed to set valid_to and is_current = false, then INSERT new versions for changed keys and brand-new keys. The generator emits both forms so you can compare. Chat2DB lets you run and inspect these statements against your warehouse — download it at https://chat2db.ai/download or use the web version at https://app.chat2db.ai.
