BTEQ scripts, FastLoad jobs, stored procedures, and Teradata SQL parsed structurally. Converted to PySpark notebooks on Databricks with Delta Lake. QUALIFY, MERGE INTO, and PRIMARY INDEX logic fully translated.
Upload a BTEQ script, get converted code →BTEQ's .LOGON, .IF/.THEN, .GOTO control flow and embedded SQL are parsed and converted to idiomatic PySpark notebooks. .LABEL and .QUIT logic becomes structured Python error handling. No more proprietary CLI scripting.
Teradata's QUALIFY clause with ROW_NUMBER(), RANK(), and DENSE_RANK() is converted to PySpark Window functions with a .filter() step. The analytical logic is preserved exactly—no manual rewrite needed.
Teradata's proprietary bulk-loading utilities—FastLoad, MultiLoad, FastExport, TPump—are replaced by Databricks Auto Loader for streaming ingestion and COPY INTO for batch loads. No Teradata channel drivers required.
A BTEQ script using QUALIFY ROW_NUMBER() for deduplication and MERGE INTO for upserts—converted to PySpark Window functions and Delta Lake merge operations.
.LOGON tdserver/dbc,dbc;
COLLECT STATISTICS ON customer_orders
COLUMN (customer_id);
CREATE VOLATILE TABLE latest_orders AS (
SELECT customer_id, order_date, amount,
order_status
FROM customer_orders
QUALIFY ROW_NUMBER() OVER (
PARTITION BY customer_id
ORDER BY order_date DESC
) = 1
) WITH DATA ON COMMIT PRESERVE ROWS;
MERGE INTO customer_summary tgt
USING latest_orders src
ON tgt.customer_id = src.customer_id
WHEN MATCHED THEN UPDATE SET
last_order_date = src.order_date,
last_amount = src.amount,
status = src.order_status
WHEN NOT MATCHED THEN INSERT VALUES (
src.customer_id, src.order_date,
src.amount, src.order_status
);
.LOGOFF;
.QUIT;
# BTEQ → PySpark on Databricks
from pyspark.sql import functions as F
from pyspark.sql.window import Window
from delta.tables import DeltaTable
spark.sql("ANALYZE TABLE customer_orders
COMPUTE STATISTICS FOR COLUMNS customer_id")
w = Window.partitionBy("customer_id") \
.orderBy(F.col("order_date").desc())
latest_orders = (
spark.read.table("customer_orders")
.withColumn("_rn", F.row_number().over(w))
.filter(F.col("_rn") == 1)
.drop("_rn")
)
tgt = DeltaTable.forName(spark, "customer_summary")
tgt.alias("tgt").merge(
latest_orders.alias("src"),
"tgt.customer_id = src.customer_id"
).whenMatchedUpdate(set={
"last_order_date": "src.order_date",
"last_amount": "src.amount",
"status": "src.order_status"
}).whenNotMatchedInsertAll().execute()
BTEQ control flow removed. QUALIFY ROW_NUMBER() becomes Window + filter. COLLECT STATISTICS becomes ANALYZE TABLE. MERGE INTO becomes Delta Lake merge. Volatile table becomes DataFrame.
| Teradata Component | Databricks Equivalent | Notes |
|---|---|---|
| BTEQ script | PySpark notebook | .LOGON/.LOGOFF removed, SQL extracted and converted |
| QUALIFY clause | Window function + .filter() | ROW_NUMBER, RANK, DENSE_RANK preserved |
| COLLECT STATISTICS | ANALYZE TABLE | Column-level statistics for query optimization |
| PRIMARY INDEX | Delta ZORDER BY | Data co-location strategy mapped |
| FastLoad | Auto Loader / COPY INTO | Streaming or batch ingestion from files |
| MultiLoad | MERGE INTO Delta | Upsert and conditional update patterns |
| Stored Procedure | Python function / notebook | Control flow and cursor logic translated |
| Macro | Parameterized notebook | Parameters via widgets, reusable execution |
| SET table | .dropDuplicates() | Unique-row enforcement at write time |
| MERGE INTO | Delta MERGE | WHEN MATCHED / NOT MATCHED fully preserved |
| Temporal table | Delta time travel | PERIOD columns become versioned Delta history |
| TPump | Structured Streaming | Near-real-time continuous ingestion |
Data Matching compares Teradata output against Databricks output—row by row, column by column. In the case study below, all BTEQ pipelines were validated with full production backtesting across 3,500 scripts.
See how Data Matching works →3,500 BTEQ scripts converted to PySpark on Databricks. 1,200 QUALIFY clauses rewritten to Window functions. FastLoad and MultiLoad jobs replaced with Auto Loader and Delta MERGE. PRIMARY INDEX strategies mapped to ZORDER. Teradata appliance decommissioned within 90 days.
Read the full case study →Upload a BTEQ script or Teradata SQL file. Get parsed lineage, PySpark code for Databricks, and a validation report.