Skip to main content

Edit a Delta table

Use this recipe to read, edit, and write back data in a Unity Catalog table using the Databricks SQL Connector.

Code snippet

app.py
import reflex as rx
from typing import Any
import pandas as pd
import datetime
from databricks import sql
from databricks.sdk.core import Config

_connection = None

def get_connection(http_path: str):
global _connection
if _connection:
return _connection
cfg = Config()
connection = sql.connect(
server_hostname=cfg.host,
http_path=http_path,
credentials_provider=cfg.authenticate,
)
_connection = connection
return connection

def insert_overwrite_table(table_name: str, df: pd.DataFrame, connection):
if df.empty:
# If the dataframe is empty, we skip the overwrite to avoid
# accidentally truncating the table if the UI state was not fully loaded.
return

def format_val(x):
if x is None or pd.isna(x):
return "NULL"
if isinstance(x, str):
return "'" + x.replace("'", "''") + "'"
if isinstance(x, (datetime.date, datetime.datetime, pd.Timestamp)):
return f"'{x}'"
return str(x)

values = []
for _, row in df.iterrows():
row_values = [format_val(val) for val in row]
values.append(f"({', '.join(row_values)})")

sql_query = f"INSERT OVERWRITE TABLE {table_name} VALUES {', '.join(values)}"

with connection.cursor() as cursor:
cursor.execute(sql_query)

class EditDeltaTableState(rx.State):
# Key state fields for managing selection and data
warehouse_paths: dict[str, str] = {}
selected_warehouse: str = ""
selected_catalog: str = ""
selected_schema: str = ""
selected_table: str = ""

# Data for the editor
columns: list[dict[str, str]] = []
table_data: list[list[Any]] = []
original_table_data: list[list[Any]] = []

is_saving: bool = False

@rx.event
def handle_cell_change(
self, new_value: Any, row_index: int, col_index: int
):
"Update table data when a cell is edited."
if row_index < len(self.table_data):
row = self.table_data[row_index]
if col_index < len(row):
self.table_data[row_index][col_index] = new_value

@rx.event
async def save_changes(self):
self.is_saving = True
yield
try:
col_names = [col["title"] for col in self.columns]
df = pd.DataFrame(self.table_data, columns=col_names)

http_path = self.warehouse_paths.get(self.selected_warehouse)
full_table_name = f"{self.selected_catalog}.{self.selected_schema}.{self.selected_table}"
conn = get_connection(http_path)

insert_overwrite_table(full_table_name, df, conn)

self.original_table_data = [row[:] for row in self.table_data]
yield rx.toast(f"Successfully saved changes to {full_table_name}.")
except Exception as e:
yield rx.toast(f"Error saving changes: {e}", level="error")
finally:
self.is_saving = False
info

This sample caches the SQL connection in a module-level _connection variable so it can be reused within the same app process. For multi-worker deployments, consider a proper pooling strategy or per-request connections depending on your workload.

Resources

Permissions

Your app service principal needs the following permissions:

  • MODIFY on the Unity Catalog table
  • CAN USE on the SQL warehouse

See Unity Catalog privileges and securable objects for more information.

Dependencies

requirements.txt
databricks-sdk
databricks-sql-connector
pandas
reflex