Databricks SQL (DBSQL) - Advanced Features
Quick Reference
| Feature |
Key Syntax |
Since |
Reference |
| SQL Scripting |
BEGIN...END, DECLARE, IF/WHILE/FOR |
DBR 16.3+ |
references/sql-scripting.md |
| Stored Procedures |
CREATE PROCEDURE, CALL |
DBR 17.0+ |
references/sql-scripting.md |
| Recursive CTEs |
WITH RECURSIVE |
DBR 17.0+ |
references/sql-scripting.md |
| Transactions |
BEGIN ATOMIC...END |
Preview |
references/sql-scripting.md |
| Materialized Views |
CREATE MATERIALIZED VIEW |
Pro/Serverless |
references/materialized-views-pipes.md |
| Temp Tables |
CREATE TEMPORARY TABLE |
All |
references/materialized-views-pipes.md |
| Pipe Syntax |
|> operator |
DBR 16.1+ |
references/materialized-views-pipes.md |
| Geospatial (H3) |
h3_longlatash3(), h3_polyfillash3() |
DBR 11.2+ |
references/geospatial-collations.md |
| Geospatial (ST) |
ST_Point(), ST_Contains(), 80+ funcs |
DBR 16.0+ |
references/geospatial-collations.md |
| Collations |
COLLATE, UTF8_LCASE, locale-aware |
DBR 16.1+ |
references/geospatial-collations.md |
| AI Functions |
ai_query(), ai_classify(), 11+ funcs |
DBR 15.1+ |
references/ai-functions.md |
| http_request |
http_request(conn, ...) |
Pro/Serverless |
references/ai-functions.md |
| remote_query |
SELECT * FROM remote_query(...) |
Pro/Serverless |
references/ai-functions.md |
| read_files |
SELECT * FROM read_files(...) |
All |
references/ai-functions.md |
| Data Modeling |
Star schema, Liquid Clustering |
All |
references/best-practices.md |
Common Patterns
SQL Scripting - Procedural ETL
BEGIN
DECLARE v_count INT;
DECLARE v_status STRING DEFAULT 'pending';
SET v_count = (SELECT COUNT(*) FROM catalog.schema.raw_orders WHERE status = 'new');
IF v_count > 0 THEN
INSERT INTO catalog.schema.processed_orders
SELECT *, current_timestamp() AS processed_at
FROM catalog.schema.raw_orders
WHERE status = 'new';
SET v_status = 'completed';
ELSE
SET v_status = 'skipped';
END IF;
SELECT v_status AS result, v_count AS rows_processed;
END
Stored Procedure with Error Handling
CREATE OR REPLACE PROCEDURE catalog.schema.upsert_customers(
IN p_source STRING,
OUT p_rows_affected INT
)
LANGUAGE SQL
SQL SECURITY INVOKER
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SET p_rows_affected = -1;
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = concat('Upsert failed for source: ', p_source);
END;
MERGE INTO catalog.schema.dim_customer AS t
USING (SELECT * FROM identifier(p_source)) AS s
ON t.customer_id = s.customer_id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;
SET p_rows_affected = (SELECT COUNT(*) FROM identifier(p_source));
END;
-- Invoke:
CALL catalog.schema.upsert_customers('catalog.schema.staging_customers', ?);
Materialized View with Scheduled Refresh
CREATE OR REPLACE MATERIALIZED VIEW catalog.schema.daily_revenue
CLUSTER BY (order_date)
SCHEDULE EVERY 1 HOUR
COMMENT 'Hourly-refreshed daily revenue by region'
AS SELECT
order_date,
region,
SUM(amount) AS total_revenue,
COUNT(DISTINCT customer_id) AS unique_customers
FROM catalog.schema.fact_orders
JOIN catalog.schema.dim_store USING (store_id)
GROUP BY order_date, region;
Pipe Syntax - Readable Transformations
-- Traditional SQL rewritten with pipe syntax
FROM catalog.schema.fact_orders
|> WHERE order_date >= current_date() - INTERVAL 30 DAYS
|> AGGREGATE SUM(amount) AS total, COUNT(*) AS cnt GROUP BY region, product_category
|> WHERE total > 10000
|> ORDER BY total DESC
|> LIMIT 20;
AI Functions - Enrich Data with LLMs
-- Classify support tickets
SELECT
ticket_id,
description,
ai_classify(description, ARRAY('billing', 'technical', 'account', 'feature_request')) AS category,
ai_analyze_sentiment(description) AS sentiment
FROM catalog.schema.support_tickets
LIMIT 100;
-- Extract entities from text
SELECT
doc_id,
ai_extract(content, ARRAY('person_name', 'company', 'dollar_amount')) AS entities
FROM catalog.schema.contracts;
-- General-purpose AI query with structured output
SELECT ai_query(
'databricks-meta-llama-3-3-70b-instruct',
concat('Summarize this customer feedback in JSON with keys: topic, sentiment, action_items. Feedback: ', feedback),
returnType => 'STRUCT<topic STRING, sentiment STRING, action_items ARRAY<STRING>>'
) AS analysis
FROM catalog.schema.customer_feedback
LIMIT 50;
Geospatial - Proximity Search with H3
-- Find stores within 5km of each customer using H3 indexing
WITH customer_h3 AS (
SELECT *, h3_longlatash3(longitude, latitude, 7) AS h3_cell
FROM catalog.schema.customers
),
store_h3 AS (
SELECT *, h3_longlatash3(longitude, latitude, 7) AS h3_cell
FROM catalog.schema.stores
)
SELECT
c.customer_id,
s.store_id,
ST_Distance(
ST_Point(c.longitude, c.latitude),
ST_Point(s.longitude, s.latitude)
) AS distance_m
FROM customer_h3 c
JOIN store_h3 s ON h3_ischildof(c.h3_cell, h3_toparent(s.h3_cell, 5))
WHERE ST_Distance(
ST_Point(c.longitude, c.latitude),
ST_Point(s.longitude, s.latitude)
) < 5000;
Collation - Case-Insensitive Search
-- Create table with case-insensitive collation
CREATE TABLE catalog.schema.products (
product_id BIGINT GENERATED ALWAYS AS IDENTITY,
name STRING COLLATE UTF8_LCASE,
category STRING COLLATE UTF8_LCASE,
price DECIMAL(10, 2)
);
-- Queries automatically case-insensitive (no LOWER() needed)
SELECT * FROM catalog.schema.products
WHERE name = 'MacBook Pro'; -- matches 'macbook pro', 'MACBOOK PRO', etc.
http_request - Call External APIs
-- Set up connection first (one-time)
CREATE CONNECTION my_api_conn
TYPE HTTP
OPTIONS (host 'https://api.example.com', bearer_token secret('scope', 'token'));
-- Call API from SQL
SELECT
order_id,
http_request(
conn => 'my_api_conn',
method => 'POST',
path => '/v1/validate',
json => to_json(named_struct('order_id', order_id, 'amount', amount))
).text AS api_response
FROM catalog.schema.orders
WHERE needs_validation = true;
read_files - Ingest Raw Files
-- Read JSON files from a Volume with schema hints
SELECT *
FROM read_files(
'/Volumes/catalog/schema/raw/events/',
format => 'json',
schemaHints => 'event_id STRING, timestamp TIMESTAMP, payload MAP<STRING, STRING>',
pathGlobFilter => '*.json',
recursiveFileLookup => true
);
-- Read CSV with options
SELECT *
FROM read_files(
'/Volumes/catalog/schema/raw/sales/',
format => 'csv',
header => true,
delimiter => '|',
dateFormat => 'yyyy-MM-dd',
schema => 'sale_id INT, sale_date DATE, amount DECIMAL(10,2), store STRING'
);
Recursive CTE - Hierarchy Traversal
WITH RECURSIVE org_chart AS (
-- Anchor: top-level managers
SELECT employee_id, name, manager_id, 0 AS depth, ARRAY(name) AS path
FROM catalog.schema.employees
WHERE manager_id IS NULL
UNION ALL
-- Recursive: direct reports
SELECT e.employee_id, e.name, e.manager_id, o.depth + 1, array_append(o.path, e.name)
FROM catalog.schema.employees e
JOIN org_chart o ON e.manager_id = o.employee_id
WHERE o.depth < 10 -- safety limit
)
SELECT * FROM org_chart ORDER BY depth, name;
remote_query - Federated Queries
-- Query PostgreSQL via Lakehouse Federation
SELECT *
FROM remote_query(
'my_postgres_connection',
database => 'my_database',
query => 'SELECT customer_id, email, created_at FROM customers WHERE active = true'
);
Reference Files
Load these for detailed syntax, full parameter lists, and advanced patterns:
| File |
Contents |
When to Read |
| references/sql-scripting.md |
SQL Scripting, Stored Procedures, Recursive CTEs, Transactions |
User needs procedural SQL, error handling, loops, dynamic SQL |
| references/materialized-views-pipes.md |
Materialized Views, Temp Tables/Views, Pipe Syntax |
User needs MVs, refresh scheduling, temp objects, pipe operator |
| references/geospatial-collations.md |
39 H3 functions, 80+ ST functions, Collation types and hierarchy |
User needs spatial analysis, H3 indexing, case/accent handling |
| references/ai-functions.md |
13 AI functions, http_request, remote_query, read_files (all options) |
User needs AI enrichment, API calls, federation, file ingestion |
| references/best-practices.md |
Data modeling, performance, Liquid Clustering, anti-patterns |
User needs architecture guidance, optimization, or modeling advice |
Key Guidelines
- Always use Serverless SQL warehouses for AI functions, MVs, and http_request
- Use
LIMIT during development with AI functions to control costs
- Prefer Liquid Clustering over partitioning for new tables (1-4 keys max)
- Use
CLUSTER BY AUTO when unsure about clustering keys
- Star schema in Gold layer for BI; OBT acceptable in Silver
- Define PK/FK constraints on dimensional models for query optimization
- Use
COLLATE UTF8_LCASE for user-facing string columns that need case-insensitive search
- Test SQL via CLI (
databricks experimental aitools tools query) or notebooks before deploying. If --warehouse is rejected on your CLI version, set DATABRICKS_WAREHOUSE_ID in the environment instead.
1---
2name: databricks-dbsql
3description: >-
4 Databricks SQL (DBSQL) advanced features and SQL warehouse capabilities.
5 This skill MUST be invoked when the user mentions: "DBSQL", "Databricks SQL",
6 "SQL warehouse", "SQL scripting", "stored procedure", "CALL procedure",
7 "materialized view", "CREATE MATERIALIZED VIEW", "pipe syntax", "|>",
8 "geospatial", "H3", "ST_", "spatial SQL", "collation", "COLLATE",
9 "ai_query", "ai_classify", "ai_extract", "ai_gen", "AI function",
10 "http_request", "remote_query", "read_files", "Lakehouse Federation",
11 "recursive CTE", "WITH RECURSIVE", "multi-statement transaction",
12 "temp table", "temporary view", "pipe operator".
13 SHOULD also invoke when the user asks about SQL best practices, data modeling
14 patterns, or advanced SQL features on Databricks.
15compatibility: Requires databricks CLI (>= v1.0.0)
16metadata:
17 version: "0.1.0"
18parent: databricks-core
19---
20
21# Databricks SQL (DBSQL) - Advanced Features
22
23## Quick Reference
24
25| Feature | Key Syntax | Since | Reference |
26|---------|-----------|-------|-----------|
27| SQL Scripting | `BEGIN...END`, `DECLARE`, `IF/WHILE/FOR` | DBR 16.3+ | [references/sql-scripting.md](references/sql-scripting.md) |
28| Stored Procedures | `CREATE PROCEDURE`, `CALL` | DBR 17.0+ | [references/sql-scripting.md](references/sql-scripting.md) |
29| Recursive CTEs | `WITH RECURSIVE` | DBR 17.0+ | [references/sql-scripting.md](references/sql-scripting.md) |
30| Transactions | `BEGIN ATOMIC...END` | Preview | [references/sql-scripting.md](references/sql-scripting.md) |
31| Materialized Views | `CREATE MATERIALIZED VIEW` | Pro/Serverless | [references/materialized-views-pipes.md](references/materialized-views-pipes.md) |
32| Temp Tables | `CREATE TEMPORARY TABLE` | All | [references/materialized-views-pipes.md](references/materialized-views-pipes.md) |
33| Pipe Syntax | `\|>` operator | DBR 16.1+ | [references/materialized-views-pipes.md](references/materialized-views-pipes.md) |
34| Geospatial (H3) | `h3_longlatash3()`, `h3_polyfillash3()` | DBR 11.2+ | [references/geospatial-collations.md](references/geospatial-collations.md) |
35| Geospatial (ST) | `ST_Point()`, `ST_Contains()`, 80+ funcs | DBR 16.0+ | [references/geospatial-collations.md](references/geospatial-collations.md) |
36| Collations | `COLLATE`, `UTF8_LCASE`, locale-aware | DBR 16.1+ | [references/geospatial-collations.md](references/geospatial-collations.md) |
37| AI Functions | `ai_query()`, `ai_classify()`, 11+ funcs | DBR 15.1+ | [references/ai-functions.md](references/ai-functions.md) |
38| http_request | `http_request(conn, ...)` | Pro/Serverless | [references/ai-functions.md](references/ai-functions.md) |
39| remote_query | `SELECT * FROM remote_query(...)` | Pro/Serverless | [references/ai-functions.md](references/ai-functions.md) |
40| read_files | `SELECT * FROM read_files(...)` | All | [references/ai-functions.md](references/ai-functions.md) |
41| Data Modeling | Star schema, Liquid Clustering | All | [references/best-practices.md](references/best-practices.md) |
42
43---
44
45## Common Patterns
46
47### SQL Scripting - Procedural ETL
48
49```sql
50BEGIN
51 DECLARE v_count INT;
52 DECLARE v_status STRING DEFAULT 'pending';
53
54 SET v_count = (SELECT COUNT(*) FROM catalog.schema.raw_orders WHERE status = 'new');
55
56 IF v_count > 0 THEN
57 INSERT INTO catalog.schema.processed_orders
58 SELECT *, current_timestamp() AS processed_at
59 FROM catalog.schema.raw_orders
60 WHERE status = 'new';
61
62 SET v_status = 'completed';
63 ELSE
64 SET v_status = 'skipped';
65 END IF;
66
67 SELECT v_status AS result, v_count AS rows_processed;
68END
69```
70
71### Stored Procedure with Error Handling
72
73```sql
74CREATE OR REPLACE PROCEDURE catalog.schema.upsert_customers(
75 IN p_source STRING,
76 OUT p_rows_affected INT
77)
78LANGUAGE SQL
79SQL SECURITY INVOKER
80BEGIN
81 DECLARE EXIT HANDLER FOR SQLEXCEPTION
82 BEGIN
83 SET p_rows_affected = -1;
84 SIGNAL SQLSTATE '45000'
85 SET MESSAGE_TEXT = concat('Upsert failed for source: ', p_source);
86 END;
87
88 MERGE INTO catalog.schema.dim_customer AS t
89 USING (SELECT * FROM identifier(p_source)) AS s
90 ON t.customer_id = s.customer_id
91 WHEN MATCHED THEN UPDATE SET *
92 WHEN NOT MATCHED THEN INSERT *;
93
94 SET p_rows_affected = (SELECT COUNT(*) FROM identifier(p_source));
95END;
96
97-- Invoke:
98CALL catalog.schema.upsert_customers('catalog.schema.staging_customers', ?);
99```
100
101### Materialized View with Scheduled Refresh
102
103```sql
104CREATE OR REPLACE MATERIALIZED VIEW catalog.schema.daily_revenue
105 CLUSTER BY (order_date)
106 SCHEDULE EVERY 1 HOUR
107 COMMENT 'Hourly-refreshed daily revenue by region'
108AS SELECT
109 order_date,
110 region,
111 SUM(amount) AS total_revenue,
112 COUNT(DISTINCT customer_id) AS unique_customers
113FROM catalog.schema.fact_orders
114JOIN catalog.schema.dim_store USING (store_id)
115GROUP BY order_date, region;
116```
117
118### Pipe Syntax - Readable Transformations
119
120```sql
121-- Traditional SQL rewritten with pipe syntax
122FROM catalog.schema.fact_orders
123 |> WHERE order_date >= current_date() - INTERVAL 30 DAYS
124 |> AGGREGATE SUM(amount) AS total, COUNT(*) AS cnt GROUP BY region, product_category
125 |> WHERE total > 10000
126 |> ORDER BY total DESC
127 |> LIMIT 20;
128```
129
130### AI Functions - Enrich Data with LLMs
131
132```sql
133-- Classify support tickets
134SELECT
135 ticket_id,
136 description,
137 ai_classify(description, ARRAY('billing', 'technical', 'account', 'feature_request')) AS category,
138 ai_analyze_sentiment(description) AS sentiment
139FROM catalog.schema.support_tickets
140LIMIT 100;
141
142-- Extract entities from text
143SELECT
144 doc_id,
145 ai_extract(content, ARRAY('person_name', 'company', 'dollar_amount')) AS entities
146FROM catalog.schema.contracts;
147
148-- General-purpose AI query with structured output
149SELECT ai_query(
150 'databricks-meta-llama-3-3-70b-instruct',
151 concat('Summarize this customer feedback in JSON with keys: topic, sentiment, action_items. Feedback: ', feedback),
152 returnType => 'STRUCT<topic STRING, sentiment STRING, action_items ARRAY<STRING>>'
153) AS analysis
154FROM catalog.schema.customer_feedback
155LIMIT 50;
156```
157
158### Geospatial - Proximity Search with H3
159
160```sql
161-- Find stores within 5km of each customer using H3 indexing
162WITH customer_h3 AS (
163 SELECT *, h3_longlatash3(longitude, latitude, 7) AS h3_cell
164 FROM catalog.schema.customers
165),
166store_h3 AS (
167 SELECT *, h3_longlatash3(longitude, latitude, 7) AS h3_cell
168 FROM catalog.schema.stores
169)
170SELECT
171 c.customer_id,
172 s.store_id,
173 ST_Distance(
174 ST_Point(c.longitude, c.latitude),
175 ST_Point(s.longitude, s.latitude)
176 ) AS distance_m
177FROM customer_h3 c
178JOIN store_h3 s ON h3_ischildof(c.h3_cell, h3_toparent(s.h3_cell, 5))
179WHERE ST_Distance(
180 ST_Point(c.longitude, c.latitude),
181 ST_Point(s.longitude, s.latitude)
182) < 5000;
183```
184
185### Collation - Case-Insensitive Search
186
187```sql
188-- Create table with case-insensitive collation
189CREATE TABLE catalog.schema.products (
190 product_id BIGINT GENERATED ALWAYS AS IDENTITY,
191 name STRING COLLATE UTF8_LCASE,
192 category STRING COLLATE UTF8_LCASE,
193 price DECIMAL(10, 2)
194);
195
196-- Queries automatically case-insensitive (no LOWER() needed)
197SELECT * FROM catalog.schema.products
198WHERE name = 'MacBook Pro'; -- matches 'macbook pro', 'MACBOOK PRO', etc.
199```
200
201### http_request - Call External APIs
202
203```sql
204-- Set up connection first (one-time)
205CREATE CONNECTION my_api_conn
206 TYPE HTTP
207 OPTIONS (host 'https://api.example.com', bearer_token secret('scope', 'token'));
208
209-- Call API from SQL
210SELECT
211 order_id,
212 http_request(
213 conn => 'my_api_conn',
214 method => 'POST',
215 path => '/v1/validate',
216 json => to_json(named_struct('order_id', order_id, 'amount', amount))
217 ).text AS api_response
218FROM catalog.schema.orders
219WHERE needs_validation = true;
220```
221
222### read_files - Ingest Raw Files
223
224```sql
225-- Read JSON files from a Volume with schema hints
226SELECT *
227FROM read_files(
228 '/Volumes/catalog/schema/raw/events/',
229 format => 'json',
230 schemaHints => 'event_id STRING, timestamp TIMESTAMP, payload MAP<STRING, STRING>',
231 pathGlobFilter => '*.json',
232 recursiveFileLookup => true
233);
234
235-- Read CSV with options
236SELECT *
237FROM read_files(
238 '/Volumes/catalog/schema/raw/sales/',
239 format => 'csv',
240 header => true,
241 delimiter => '|',
242 dateFormat => 'yyyy-MM-dd',
243 schema => 'sale_id INT, sale_date DATE, amount DECIMAL(10,2), store STRING'
244);
245```
246
247### Recursive CTE - Hierarchy Traversal
248
249```sql
250WITH RECURSIVE org_chart AS (
251 -- Anchor: top-level managers
252 SELECT employee_id, name, manager_id, 0 AS depth, ARRAY(name) AS path
253 FROM catalog.schema.employees
254 WHERE manager_id IS NULL
255
256 UNION ALL
257
258 -- Recursive: direct reports
259 SELECT e.employee_id, e.name, e.manager_id, o.depth + 1, array_append(o.path, e.name)
260 FROM catalog.schema.employees e
261 JOIN org_chart o ON e.manager_id = o.employee_id
262 WHERE o.depth < 10 -- safety limit
263)
264SELECT * FROM org_chart ORDER BY depth, name;
265```
266
267### remote_query - Federated Queries
268
269```sql
270-- Query PostgreSQL via Lakehouse Federation
271SELECT *
272FROM remote_query(
273 'my_postgres_connection',
274 database => 'my_database',
275 query => 'SELECT customer_id, email, created_at FROM customers WHERE active = true'
276);
277```
278
279---
280
281## Reference Files
282
283Load these for detailed syntax, full parameter lists, and advanced patterns:
284
285| File | Contents | When to Read |
286|------|----------|--------------|
287| [references/sql-scripting.md](references/sql-scripting.md) | SQL Scripting, Stored Procedures, Recursive CTEs, Transactions | User needs procedural SQL, error handling, loops, dynamic SQL |
288| [references/materialized-views-pipes.md](references/materialized-views-pipes.md) | Materialized Views, Temp Tables/Views, Pipe Syntax | User needs MVs, refresh scheduling, temp objects, pipe operator |
289| [references/geospatial-collations.md](references/geospatial-collations.md) | 39 H3 functions, 80+ ST functions, Collation types and hierarchy | User needs spatial analysis, H3 indexing, case/accent handling |
290| [references/ai-functions.md](references/ai-functions.md) | 13 AI functions, http_request, remote_query, read_files (all options) | User needs AI enrichment, API calls, federation, file ingestion |
291| [references/best-practices.md](references/best-practices.md) | Data modeling, performance, Liquid Clustering, anti-patterns | User needs architecture guidance, optimization, or modeling advice |
292
293---
294
295## Key Guidelines
296
297- **Always use Serverless SQL warehouses** for AI functions, MVs, and http_request
298- **Use `LIMIT` during development** with AI functions to control costs
299- **Prefer Liquid Clustering over partitioning** for new tables (1-4 keys max)
300- **Use `CLUSTER BY AUTO`** when unsure about clustering keys
301- **Star schema in Gold layer** for BI; OBT acceptable in Silver
302- **Define PK/FK constraints** on dimensional models for query optimization
303- **Use `COLLATE UTF8_LCASE`** for user-facing string columns that need case-insensitive search
304- **Test SQL via CLI** (`databricks experimental aitools tools query`) or notebooks before deploying. If `--warehouse` is rejected on your CLI version, set `DATABRICKS_WAREHOUSE_ID` in the environment instead.