Snowflake Time Travel: SQL Recovery & UNDROP Guide

Brolly Academy | Snowflake Guides

Investigate a bad update, preserve a valid later change and validate dropped-table recovery.

Follow the numbered implementation, compare expected results and document your own run. Explore the Snowflake course for a structured learning path.

Share

Snowflake Time Travel — Brolly Academy history and recovery guide

Table of Contents

What is Snowflake Time Travel?

Snowflake Time Travel lets you inspect retained historical data and restore eligible dropped objects within their retention period. Use historical queries to identify a known-good state, validate it and choose a controlled recovery action. The correct recovery point matters as much as the recovery command.

This guide works through an accidental inventory-price update, a selective row repair and a dropped-table recovery. For a separate development copy, use the zero-copy cloning guide. The focus here is incident evidence, historical query boundaries and recovery validation.

Before you start

  • Level: Beginner to intermediate SQL.
  • Planning time: 45–75 minutes; account access and troubleshooting may take longer.
  • Deliverable: A validated price repair that preserves a later valid name change, plus an UNDROP drill.
  • Requirements: an approved practice database, the privileges described below and an existing lab warehouse.
  • Cost: compute and storage are usage-based. Use synthetic data, keep the batch small and follow the cleanup steps.

1. Match the command to what actually went wrong

SituationStarting actionQuestion before repair
A committed UPDATE changed valuesQuery the retained state around the statementWhich rows were wrong, and what valid changes followed?
A committed DELETE removed recordsInspect historical rowsShould those records still exist under today’s business rules?
A table was droppedCheck eligibility for UNDROP TABLEIs the dropped object retained, and is its name available?
Analyst needs an earlier reportUse an appropriate historical query pointWhich data version and timestamp define that report?
History has expiredUse the established recovery/replay planWhat evidence and retained sources remain available?

Do not assume that every incident should restore an entire table. A full rollback can remove valid later updates. First determine whether the repair unit is one attribute, selected rows, an entire table or a larger group of related objects.

The Time Travel guide explains the feature and retention. The workflow below adds an original, small repair exercise whose before/after values can be checked manually.

Snowflake Time Travel conceptual workflow with Brolly Academy logo and contact details
Conceptual workflow for this lab; not a Snowflake execution screenshot.

2. Check retention, table type and account edition

For ordinary Snowflake tables, the standard Time Travel retention is one day. Standard Edition supports the ordinary zero/one-day configuration; eligible permanent objects on Enterprise Edition or higher can have longer retention, up to 90 days. Transient and temporary objects do not receive that same extended permanent-table range. Zero effective retention disables the historical recovery behavior you would expect from this exercise.

Check the effective settings on the actual object, not a remembered account default. Account-level minimums and inheritance can affect the final behavior. This tutorial sets one day on a new permanent lab table without changing any account-wide setting.

-- Select an approved practice database first.
USE WAREHOUSE BA_LAB_WH;
CREATE SCHEMA BA_TT_LAB;
USE SCHEMA BA_TT_LAB;

CREATE TABLE PRODUCT_PRICES (
 product_id NUMBER, product_name VARCHAR, unit_price NUMBER(10,2)
) DATA_RETENTION_TIME_IN_DAYS=1;

INSERT INTO PRODUCT_PRICES VALUES
 (1,'Notebook',100.00),
 (2,'Backpack',500.00),
 (3,'Pen set',50.00);

SHOW PARAMETERS LIKE 'DATA_RETENTION_TIME_IN_DAYS'
  IN TABLE PRODUCT_PRICES;
SELECT * FROM PRODUCT_PRICES ORDER BY product_id;

Use a new empty lab schema. The script avoids CREATE OR REPLACE so a rerun does not erase or replace the very object identity whose history you are trying to understand. Keep all later commands in the same worksheet session unless you explicitly re-establish variables and object context.

2.1 Establish a clear incident-drill starting point

  1. Use a new empty BA_TT_LAB schema in an approved practice database.
  2. Create PRODUCT_PRICES with positive retention and insert the three synthetic rows once.
  3. Record the database, schema, role, warehouse and table-level retention output.
  4. Keep the worksheet session open for the incident query-ID variable.
  5. Confirm the initial values before simulating a mistake. Stop if the source is not the supplied three-row seed.
SELECT CURRENT_DATABASE(),CURRENT_SCHEMA(),CURRENT_ROLE(),CURRENT_WAREHOUSE();
SELECT COUNT(*) AS baseline_rows,SUM(unit_price) AS baseline_total FROM PRODUCT_PRICES;
SELECT product_id,COUNT(*) AS copies FROM PRODUCT_PRICES
GROUP BY product_id HAVING COUNT(*)>1;
SHOW TABLES LIKE 'PRODUCT_PRICES' IN SCHEMA BA_TT_LAB;

Expected baseline: three rows, total 650.00 and no duplicate IDs. Positive retention enables this time-bounded historical drill; it does not create an unlimited backup. Check both effective settings and the actual history available before attempting a recovery.

3. Understand AT, BEFORE, timestamps and offsets

  1. AT: request the state at the specified point, with inclusive boundary behavior.
  2. BEFORE: request the state immediately preceding the specified statement boundary.
  3. TIMESTAMP: identify a fixed time with an explicit timestamp type and time-zone interpretation.
  4. OFFSET: identify a time relative to the present, in seconds.
  5. STATEMENT: identify a supported statement through its actual query ID.

A relative offset moves as time passes. It can be convenient during exploration, but “five minutes ago” is a poor permanent incident record. Save a real query ID or an explicit fixed timestamp when documenting a repair. Statement-ID lookup also has its own supported age limit; a longer object-retention period does not remove that lookup constraint.

Read the AT / BEFORE reference for boundary and timestamp details. BEFORE identifies the point just before the referenced statement completes, not a universal guarantee that no concurrent transaction had committed since it started. Investigate concurrency when the source was being actively written.

3.1 Choose the right historical reference

ReferenceUseful forCommon mistake
BEFORE(STATEMENT => query_id)Inspecting the state preceding the known bad statement boundaryCapturing a different statement ID after extra worksheet queries
AT(TIMESTAMP => typed timestamp)Reproducing an explicitly recorded timeUsing a time-zone interpretation different from the incident log
AT(OFFSET => negative seconds)Short exploratory checksTreating a moving relative time as a permanent recovery reference

For this drill, use the captured bad-update ID. If LAST_QUERY_ID was captured too late, inspect the worksheet query history and identify the real UPDATE before continuing. Do not repeatedly guess offsets until one appears to produce a plausible total. Match object identity, affected keys and the incident timeline.

A timestamp can identify a retained point even when statement-ID lookup limits are relevant, but it must be chosen from actual incident evidence. Historical queries cannot reach before the object existed, and replacement or recreation changes the identity assumptions. See the AT / BEFORE boundary reference.

4. Simulate a bad update and capture its query ID

In this isolated example, someone intended to discount one product but forgot the WHERE clause. All three prices are multiplied by ten. Run the SET statement immediately after the UPDATE in the same session so LAST_QUERY_ID identifies the intended statement.

UPDATE PRODUCT_PRICES SET unit_price=unit_price*10;
SET bad_update_qid = LAST_QUERY_ID();

SELECT $bad_update_qid AS incident_query_id;
SELECT * FROM PRODUCT_PRICES ORDER BY product_id;

SELECT * FROM PRODUCT_PRICES
BEFORE(STATEMENT => $bad_update_qid)
ORDER BY product_id;
Product IDBefore bad updateCurrent after bad update
1100.001000.00
2500.005000.00
350.00500.00

The known-good price total is 650.00; the bad-state total is 6500.00. Summing prices is only a compact lab reconciliation, not a meaningful revenue metric. Keep the three row-level comparisons because equal totals alone could hide one price increasing while another decreases.

5. Create an inspectable recovery snapshot

CREATE TABLE PRICES_BEFORE_BAD_UPDATE AS
SELECT * FROM PRODUCT_PRICES
BEFORE(STATEMENT => $bad_update_qid);

SELECT COUNT(*) AS rows, SUM(unit_price) AS price_total
FROM PRICES_BEFORE_BAD_UPDATE;

SELECT product_id, COUNT(*) AS copies
FROM PRICES_BEFORE_BAD_UPDATE
GROUP BY product_id HAVING COUNT(*)>1;

This is a new table populated by a historical query, rather than an in-place change to the live data. It provides a stable comparison artifact while you decide what to repair. Expected snapshot checks are three rows, total price 650.00 and no duplicate product IDs.

Before a real repair, record who approved the chosen recovery point, the affected keys and the columns that may be overwritten. Preserve the current damaged state when it contains evidence needed for investigation. In this small lab, the price error is already visible and reproducible from the saved query ID.

Workflow: Incident query ID → historical snapshot → row comparison
Approved repair scope → transactional update → before/after validation

5.1 Build a row-level incident difference report

Run this after creating PRICES_BEFORE_BAD_UPDATE and before repairing the current values. It shows why the change is considered wrong instead of relying on the total alone.

SELECT t.product_id,t.product_name,
 r.unit_price AS known_good_price,t.unit_price AS current_price,
 t.unit_price-r.unit_price AS price_difference
FROM PRODUCT_PRICES t
JOIN PRICES_BEFORE_BAD_UPDATE r USING(product_id)
WHERE t.unit_price IS DISTINCT FROM r.unit_price
ORDER BY t.product_id;
Product IDKnown-good priceBad current priceDifference
1100.001000.00900.00
2500.005000.004500.00
350.00500.00450.00

IS DISTINCT FROM also detects a NULL-versus-value mismatch. Save the historical extract, incident query ID and this difference report before changing current data. In a real incident, add an approved affected-key list; historical data alone does not authorize changing every row.

6. Repair selected attributes while preserving a valid later change

Now simulate a legitimate update after the mistake: the product team corrects the backpack’s display name. Restoring every old column would undo that valid correction. We will repair only unit_price and leave the current name intact.

UPDATE PRODUCT_PRICES
SET product_name='Travel backpack' WHERE product_id=2;

BEGIN;
UPDATE PRODUCT_PRICES t
SET unit_price=r.unit_price
FROM PRICES_BEFORE_BAD_UPDATE r
WHERE t.product_id=r.product_id;

SELECT * FROM PRODUCT_PRICES ORDER BY product_id;
SELECT COUNT(*) AS mismatched_prices
FROM PRODUCT_PRICES t
JOIN PRICES_BEFORE_BAD_UPDATE r USING(product_id)
WHERE t.unit_price <> r.unit_price;
-- STOP: keep this transaction open and inspect both result sets.

Stop and choose one transaction action before continuing. Inspect the preceding output in the same session: three rows, 650.00 total, expected prices and the valid Travel backpack name. If correct, execute the following COMMIT block separately. If not, execute ROLLBACK instead. Do not run both, and do not begin the next drill with this transaction open.

COMMIT;

Alternative only if validation fails:

ROLLBACK;

For the supplied lab, mismatched_prices should be zero. Product 2 should now be named Travel backpack with a price of 500.00. The other products should be Notebook/100.00 and Pen set/50.00. Before COMMIT in an exploratory run, choose ROLLBACK if the results do not match the intended repair.

In a real incident, a later valid price update complicates this repair too. A historical price must not overwrite a newer approved price simply because it predates the incident. Establish a write pause, an approved affected-key set or a change-aware repair rule as appropriate to the system. Time Travel supplies evidence; it does not decide which later business changes to preserve.

Check missing and unexpected keys as well

SELECT COALESCE(t.product_id,r.product_id) AS product_id,
 CASE WHEN t.product_id IS NULL THEN 'MISSING_CURRENT'
      WHEN r.product_id IS NULL THEN 'NOT_IN_SNAPSHOT'
 END AS key_exception
FROM PRODUCT_PRICES t
FULL OUTER JOIN PRICES_BEFORE_BAD_UPDATE r USING(product_id)
WHERE t.product_id IS NULL OR r.product_id IS NULL;

The seed should produce no key exceptions. Outside this lab, an exception may be a valid later insert rather than an error. Investigate it using the incident scope. Do not make the recovery snapshot’s key set automatically authoritative for all later business activity.

6.1 Verify the repaired business state with a full comparison

Run this after the selective repair and legitimate name update. The correct output combines historical prices with the current approved product name; it is deliberately not identical to the entire historical snapshot.

WITH expected(product_id,product_name,unit_price) AS (
 SELECT * FROM VALUES (1,'Notebook',100.00),
 (2,'Travel backpack',500.00),(3,'Pen set',50.00)
)
SELECT 'MISSING_OR_WRONG' AS issue,* FROM (
 SELECT * FROM expected MINUS SELECT * FROM PRODUCT_PRICES
)
UNION ALL
SELECT 'UNEXPECTED_OR_WRONG' AS issue,* FROM (
 SELECT * FROM PRODUCT_PRICES MINUS SELECT * FROM expected
);
SELECT COUNT(*) AS rows_after_repair,SUM(unit_price) AS total_after_repair
FROM PRODUCT_PRICES;
SELECT product_id,COUNT(*) AS copies FROM PRODUCT_PRICES
GROUP BY product_id HAVING COUNT(*)>1;

Expect zero difference rows, three current rows, total 650.00 and zero duplicate IDs. A whole-table restoration could pass the price-total check while silently reverting Travel backpack to Backpack. This is why the acceptance specification includes a later valid change.

6.2 Practise a missing-row repair on a disposable copy

This is a separate extension. Create a scratch copy from the repaired table, delete product 3 there and restore only that row from the retained pre-delete state. Do not run the DELETE against PRODUCT_PRICES.

CREATE TABLE PRICE_DELETE_DRILL DATA_RETENTION_TIME_IN_DAYS=1 AS SELECT * FROM PRODUCT_PRICES;
DELETE FROM PRICE_DELETE_DRILL WHERE product_id=3;
SET delete_qid=LAST_QUERY_ID();
SELECT * FROM PRICE_DELETE_DRILL BEFORE(STATEMENT => $delete_qid)
WHERE product_id=3;
BEGIN;
INSERT INTO PRICE_DELETE_DRILL(product_id,product_name,unit_price)
SELECT h.product_id,h.product_name,h.unit_price
FROM PRICE_DELETE_DRILL BEFORE(STATEMENT => $delete_qid) h
WHERE h.product_id=3
 AND NOT EXISTS(SELECT 1 FROM PRICE_DELETE_DRILL c WHERE c.product_id=h.product_id);
SELECT COUNT(*) AS restored_rows,SUM(unit_price) AS restored_total FROM PRICE_DELETE_DRILL;
-- STOP: expected three rows and 650.00. Inspect before choosing an action.

Stop and choose one transaction action before continuing. Inspect the preceding output in the same session: three rows, 650.00 total, expected prices and the valid Travel backpack name. If correct, execute the following COMMIT block separately. If not, execute ROLLBACK instead. Do not run both, and do not begin the next drill with this transaction open.

COMMIT;

Alternative only if validation fails:

ROLLBACK;

The anti-join prevents a second sequential run from adding the already restored key. It is not a concurrency guarantee: coordinate writers and validate uniqueness before a real repair. If validation fails inside the transaction, choose ROLLBACK instead of COMMIT. Keep DDL outside the repair transaction.

7. Practise dropped-table recovery separately

A dropped-table incident needs object recovery rather than an UPDATE. Create a dedicated scratch copy, drop it, then restore it while it is eligible. This exercise avoids dropping the repaired PRODUCT_PRICES table.

CREATE TABLE DROP_RECOVERY_DEMO AS
SELECT * FROM PRODUCT_PRICES;
SHOW PARAMETERS LIKE 'DATA_RETENTION_TIME_IN_DAYS'
  IN TABLE DROP_RECOVERY_DEMO;
-- Confirm a positive effective retention setting before proceeding.
DROP TABLE DROP_RECOVERY_DEMO;
UNDROP TABLE DROP_RECOVERY_DEMO;

SELECT COUNT(*) AS rows, SUM(unit_price) AS price_total
FROM DROP_RECOVERY_DEMO;

Expected restored values are three rows and a price total of 650.00. The current Travel backpack name should also remain. Use the UNDROP TABLE reference for object eligibility and name-conflict rules. If an active table already uses the name, inspect it before considering a rename; do not drop that active object as a reflex.

If the database or schema containing an object was dropped, recovery involves the container context too. The point of the small table-only exercise is to learn one boundary cleanly before attempting a broader incident. A production runbook should identify the affected object hierarchy and confirm grants and downstream behavior after recovery.

7.1 Verify values and names after UNDROP

After the section-7 scratch-table UNDROP, compare both directions against PRODUCT_PRICES, then check uniqueness separately.

SELECT * FROM DROP_RECOVERY_DEMO MINUS SELECT * FROM PRODUCT_PRICES;
SELECT * FROM PRODUCT_PRICES MINUS SELECT * FROM DROP_RECOVERY_DEMO;
SELECT product_id,COUNT(*) AS copies FROM DROP_RECOVERY_DEMO
GROUP BY product_id HAVING COUNT(*)>1;

All three queries should return no rows for this seed. Also confirm the restored object is usable by the intended reader role and that the expected downstream queries work. A successful UNDROP message is an object-recovery result, not complete business validation.

  1. If the name is occupied, identify the active and dropped objects first.
  2. Preserve the active object and agree a controlled rename plan where necessary.
  3. Restore only an eligible retained object using the correct database/schema context.
  4. Recheck values, grants and consumers before declaring the incident resolved.

The UNDROP TABLE reference explains eligibility and name conflicts. Do not drop a current table just to clear a name without first understanding its data and dependencies.

8. Build a recovery validation record

  1. Identity: record database, schema, object name and relevant object version or incident query ID.
  2. Scope: record affected keys and attributes, plus later changes intentionally preserved.
  3. Baseline: retain the historical row extract or a suitable controlled snapshot.
  4. Checks: compare row counts, keys, important values and downstream business metrics.
  5. Execution: retain repair query IDs, transaction outcome and actual validation output.
  6. Follow-through: identify downstream jobs, reports or consumers that need a consistency check.

For this lab, a complete evidence sheet shows 650.00 before the error, 6500.00 after it, 650.00 after repair and the preserved product-name correction. Add a short statement explaining why a whole-table replacement would have been a worse repair for that specific sequence of changes.

8.1 Use an incident evidence sheet with measurable acceptance criteria

Evidence fieldThis drillWhat to record in a real run
Recovery pointBefore saved bad UPDATEActual query ID or fixed typed timestamp
Repair scopeunit_price for three seeded keysApproved keys/columns and excluded later changes
Known-good state3 rows; 650.00Retained extract and row-level business checks
Damaged state3 rows; 6500.00Observed values and affected consumers
Recovered state3 rows; 650.00; Travel backpack preservedActual assertions and transaction outcome
Follow-upSeparate UNDROP and DELETE drillsDependent refreshes, reader access and incident timeline

Measure elapsed recovery time only during an actual run with a defined start and completion condition. A tiny training example cannot substantiate an enterprise recovery-time objective. Save SQL, approvals where applicable, query IDs and observed results in the same evidence package.

9. Distinguish Time Travel, cloning and Fail-safe

Time Travel provides retained historical access within its supported window. Cloning creates another object and can be combined with a historical point where supported; our cloning tutorial explains that implementation step by step. Fail-safe is a separate recovery mechanism rather than a historical table you can browse with SELECT. Consult its official reference when planning beyond user-accessible retention.

Neither an attractive retention setting nor a successful UNDROP test is a complete continuity plan. Think about source replay, permissions, object dependencies, replication requirements and how the business will recognize a recovered dataset as correct. Keep an incident drill small enough that you can explain every restored value.

10. Balance retention with storage and recovery needs

Longer retention can keep more historical changed data and affect storage usage. The amount depends on change patterns, table types and account settings. Use Snowflake’s storage considerations and actual account usage before proposing a monetary estimate.

For a training exercise, keep the one-day table-level configuration and finish promptly. Do not change an account-wide retention policy simply to make a sample work. For a business workload, define the recovery objective first: how quickly must an error be noticed, and how far back must an operator be able to inspect the data?

10.1 Retention is a policy decision, not a reset button

Retention must be long enough to cover how quickly the organization discovers errors and chooses a repair. Longer retained history can increase storage usage, but table size alone is not a bill: changed-data volume and table type matter. Never reduce retention on a live table simply to clean up this tutorial.

After review, remove only the disposable drill objects using your normal account process. Keep the evidence export if it is needed for your portfolio. For a wider recovery design, distinguish user-accessible Time Travel, historical zero-copy cloning, source replay and the separate Fail-safe mechanism.

11. Troubleshoot historical access and recovery

SymptomCheck firstNext action
Time Travel data unavailableRetention and object creation timeConfirm the requested history belongs to this object and still exists
Wrong historical rowsBoundary, time zone and incident statementUse the actual query ID or an explicitly typed fixed timestamp
Statement not foundID accuracy and supported lookup ageUse an appropriate timestamp if retained history is still available
UNDROP name conflictCurrent active object with the same nameInspect both object identities before a controlled rename plan
Prices fixed; another column revertedWhole-row overwriteRepair only approved attributes and preserve valid later changes
Counts match; report is wrongValues, keys and downstream refreshReconcile the business output and its refresh state

12. Explain the recovery rather than reciting commands

Include the SQL, incident query ID, expected values, actual comparisons and a short repair rationale in your portfolio. Explain that the recovery snapshot supplied historical evidence while the repair policy preserved a later valid name change.

  1. When would you use BEFORE rather than AT for a bad statement?
  2. Why is a relative offset unsuitable as the only long-term incident reference?
  3. How can a complete table restoration lose valid changes?
  4. What happens if the requested history is no longer retained?
  5. Why check the effective object setting instead of relying only on an edition’s maximum?
  6. How would you validate the downstream report after recovery?

After completing the drill, a résumé point can describe a Snowflake recovery exercise using statement-based historical queries, selective attribute repair and dropped-table validation. Avoid claiming a recovery-time objective until it has been measured under the relevant conditions. See the Snowflake interview guide for additional questions.

13. Frequently asked questions

Does Time Travel automatically undo a committed mistake?

No. Query the historical evidence, choose a repair and verify the resulting state. Reading an older version does not change the current table.

Can I recover any table from 90 days ago?

No. Eligibility depends on table type, account edition, effective retention and whether the specific history is still available. Ninety days is a supported maximum for eligible permanent objects, not an account-wide guarantee.

Should I use CREATE OR REPLACE to reset this exercise?

Use a new lab schema for a fresh run. Replacing the source object changes the history and identity assumptions the recovery drill is designed to teach.

Were these recovery commands executed?

No connected Snowflake execution was performed. The expected row values and totals are independently reconciled, and the command patterns were checked against official documentation. Record your own results and transaction decisions.

What is the difference between AT and BEFORE in Snowflake Time Travel?

AT requests the state at its supported boundary; BEFORE requests the state preceding the referenced statement boundary. Use the actual incident statement and documented concurrency semantics rather than treating the keywords as interchangeable.

Why save LAST_QUERY_ID immediately after the bad UPDATE?

Additional worksheet statements can change which query is last. Capturing immediately in the same session makes the incident reference explicit. If you capture the wrong one, identify the correct UPDATE in query history.

Can Time Travel restore only a deleted row?

Yes, query the retained historical row and design an INSERT that restores only the approved missing key. The disposable DELETE drill includes a sequential rerun guard, transaction inspection and value validation.

Why does a recovered total of 650 not prove success?

Incorrect rows can produce the same total, and a whole-row restore can lose a legitimate name correction. Compare keys, values, duplicates and intentionally preserved later changes.

Can I use UNDROP when the same table name already exists?

An active name conflict must be resolved through a deliberate object-identity and rename plan. Do not discard the active table as an automatic troubleshooting step.

Is Time Travel the same as Fail-safe?

No. Time Travel supports user-accessible retained historical operations. Fail-safe is a separate recovery mechanism and is not a period you browse with ordinary historical SELECT queries.

Does changing retention restore history that has already expired?

Do not assume a later setting can recreate unavailable history. Check the actual retained data and use the established replay or recovery plan when the desired point is unavailable.

How do I prevent a repair from undoing valid later changes?

Define affected keys and columns, examine later writes and coordinate concurrent writers. The main lab restores only unit_price while retaining Travel backpack. A real system may also need a change-aware rule or write pause.

For broader hands-on work, continue with Snowflake projects. For guided learning, review the Snowflake course syllabus and confirm the recovery exercises covered in the current batch.

Key Takeaways

  • Capture the incident statement boundary before running unrelated statements.
  • Recover only the damaged attributes when later valid changes must survive.
  • Validate exact rows and keys before choosing COMMIT or ROLLBACK.

Conclusion

Snowflake Time Travel becomes useful when you can explain the workflow, validate its outputs and recover from the failure cases. Complete the baseline before the optional drills, save your evidence and follow the cleanup guidance. The supplied examples use synthetic inputs; expected outputs are not presented as account execution screenshots.

Related Snowflake Articles

Snowflake Projects

Choose a portfolio exercise with SQL, expected results and validation steps.

Snowflake Interview Questions

Practise explaining SQL, validation and project decisions.

Snowflake Certification

Explore the separate certification learning path and exam preparation.

Related Courses

Snowflake Training

Explore the syllabus, practical learning topics and available Snowflake training formats.

dbt Course

Explore analytics engineering and SQL transformation workflows with dbt.

Azure Data Factory Training

Explore data integration, orchestration and cloud pipeline training.