<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>article Integrating Apache Spark™ with Databricks Unity Catalog Assets via Open APIs in Technical Blog</title>
    <link>https://community.databricks.com/t5/technical-blog/integrating-apache-spark-with-databricks-unity-catalog-assets/ba-p/97533</link>
    <description>&lt;P&gt;&lt;A href="https://www.databricks.com/product/unity-catalog" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Databricks Unity Catalog&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt; (UC) is the industry’s only unified and open governance solution for data and AI, built into the &lt;/SPAN&gt;&lt;A href="https://www.databricks.com/product/data-intelligence-platform?scid=7018Y000001f8FCQAY&amp;amp;utm_medium=paid+search&amp;amp;utm_source=google&amp;amp;utm_campaign=20771864799&amp;amp;utm_adgroup=153516637417&amp;amp;utm_content=product+page&amp;amp;utm_offer=data-intelligence-platform&amp;amp;utm_ad=680871359457&amp;amp;utm_term=databricks%20intelligence%20engine&amp;amp;gad_source=1&amp;amp;gclid=CjwKCAjwg-24BhB_EiwA1ZOx8rGj-W0294YatrdxAa0YwboofPPXtOS_a4l2Q5ka2F1brE0tWkGxDBoCqIcQAvD_BwE" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Databricks Data Intelligence Platform&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;. Unity Catalog provides a single source of truth for your organization’s data and AI assets, with open connectivity to any data source and any format, unified governance with detailed lineage tracking, comprehensive monitoring, and support for open sharing and collaboration.&lt;/SPAN&gt;&lt;A href="https://www.databricks.com/product/unity-catalog" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;With its open APIs and introduction of credential vending, Databricks Unity Catalog data can be read by external engines and interfaces such as Iceberg REST APIs, DuckDB, Apache Spark™, Trino.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;In this blog, we explore how&lt;/SPAN&gt;&lt;SPAN&gt; you can use Apache Spark&lt;/SPAN&gt;&lt;SPAN&gt; from an external (non-Databricks) processing engine to securely perform&lt;/SPAN&gt;&lt;SPAN&gt; CRUD&lt;/SPAN&gt;&lt;SPAN&gt; (Create, Read, Update, and Delete) operations on your tables registered in a&lt;/SPAN&gt; &lt;SPAN&gt;Databricks Unity Catalog, using UC’s open source REST APIs and Iceberg Rest Catalog (IRC) APIs.&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://www.databricks.com/product/unity-catalog" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;You can now use Spark SQL and DataFrame APIs to operate on Databricks Unity Catalog tables from an external processing engine, without having to configure your entire Spark application with one set of credentials to allow access to all your tables. Instead, the Spark integration will automatically acquire per-table credentials from UC (assuming the user has the necessary permissions) when running your Spark jobs.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;I&gt;&lt;SPAN&gt;If you’d like to learn how you can set up your own Unity Catalog server and use&lt;/SPAN&gt;&lt;/I&gt;&lt;I&gt;&lt;SPAN&gt; Apache Spark™&lt;/SPAN&gt;&lt;/I&gt;&lt;I&gt;&lt;SPAN&gt; from an external (non-Databricks) processing engine to securely perform&lt;/SPAN&gt;&lt;/I&gt;&lt;I&gt;&lt;SPAN&gt; CRUD&lt;/SPAN&gt;&lt;/I&gt;&lt;I&gt;&lt;SPAN&gt; operations on your Delta tables registered in&lt;/SPAN&gt;&lt;/I&gt;&lt;I&gt;&lt;SPAN&gt; a &lt;/SPAN&gt;&lt;/I&gt;&lt;A href="https://www.unitycatalog.io/" target="_blank" rel="noopener"&gt;&lt;I&gt;&lt;SPAN&gt;Unity Catalog OSS&lt;/SPAN&gt;&lt;/I&gt;&lt;/A&gt;&lt;I&gt;&lt;SPAN&gt; metastore using UC’s open source REST APIs, please refer to this &lt;/SPAN&gt;&lt;/I&gt;&lt;A href="https://www.unitycatalog.io/blogs/integrating-apache-spark-with-unity-catalog-assets-via-open-apis" target="_blank" rel="noopener"&gt;&lt;I&gt;&lt;SPAN&gt;blog&lt;/SPAN&gt;&lt;/I&gt;&lt;/A&gt;&lt;I&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;/I&gt;&lt;I&gt;&lt;/I&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Securing Access Requests from External Engines&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;When Apache Spark requests access to data in a table registered in a Databricks UC metastore from an external processing engine, Unity Catalog issues short-lived credentials and URLs to control storage access based on the user’s specific IAM roles or managed identities, enabling data retrieval and query execution. The detailed steps are captured in the diagram below.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="dkushari_0-1730724640060.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/12574i1C8206298DEE4989/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_0-1730724640060.png" alt="dkushari_0-1730724640060.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Experiencing Apache Spark in Action with Unity Catalog’s Open APIs&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;In this section, we’ll look at how you can perform CRUD operations on tables registered in&lt;/SPAN&gt; &lt;SPAN&gt;Databricks Unity Catalog using Spark SQL and PySpark DataFrame APIs. We’ll walk through the following steps:&lt;/SPAN&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Setting up Apache Spark on the local workstation&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Accessing Databricks UC from the local terminal&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Performing CRUD operations on Delta tables in Databricks UC from the local terminal&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Performing a UC access control test&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Performing CRUD operations on Managed Iceberg tables in Databricks UC from the local terminal&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Accessing UniForm Iceberg tables in Databricks UC from the local terminal&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;H3&gt;&lt;SPAN&gt;Step 1: Setting up Apache Spark on the local workstation&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;The first step is to download and configure Apache Spark. You can download the latest version (In this blog, I used &lt;/SPAN&gt;&lt;STRONG&gt;spark-4.0.1&lt;/STRONG&gt;&lt;SPAN&gt;) of Spark (&amp;gt;= 4.0.1) using a command like the following:&lt;/SPAN&gt;&lt;/P&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="python"&gt;curl -O https://archive.apache.org/dist/spark/spark-4.0.1/spark-4.0.1-bin-hadoop3.tgz&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&lt;SPAN&gt;Next, untar the package using the following command (for the rest of this tutorial, I’ll consider you’re using &lt;/SPAN&gt;&lt;STRONG&gt;spark-4.0.1&lt;/STRONG&gt;) :&lt;/P&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="python"&gt;tar xzf spark-4.0.1-bin-hadoop3.tgz&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;H3&gt;&lt;SPAN&gt;Step 2: Accessing Databricks UC from the local terminal&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;You can access Databricks UC from Apache Spark via the terminal using the Spark SQL shell or the PySpark shell.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H4&gt;&lt;SPAN&gt;Accessing Databricks UC from the Spark SQL shell&lt;/SPAN&gt;&lt;/H4&gt;
&lt;P&gt;&lt;SPAN&gt;To use the Spark SQL shell (&lt;/SPAN&gt;&lt;SPAN&gt;bin/spark-sql&lt;/SPAN&gt;&lt;SPAN&gt;), go into the &lt;/SPAN&gt;&lt;SPAN&gt;bin&lt;/SPAN&gt;&lt;SPAN&gt; folder inside the downloaded Apache Spark folder (&lt;/SPAN&gt;&lt;SPAN&gt;spark-4.0.1-bin-hadoop3&lt;/SPAN&gt;&lt;SPAN&gt;) in your terminal:&lt;/SPAN&gt;&lt;/P&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="markup"&gt;cd spark-4.0.1-bin-hadoop3/bin&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&lt;SPAN&gt;Once you’re inside the &lt;/SPAN&gt;&lt;SPAN&gt;bin&lt;/SPAN&gt;&lt;SPAN&gt; folder, run the following command to launch the &lt;/SPAN&gt;&lt;SPAN&gt;spark-sql&lt;/SPAN&gt;&lt;SPAN&gt; shell (see below for a discussion of the packages and configuration options):&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;TABLE style="border-style: hidden;"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;LI-CODE lang="python"&gt;./spark-sql --name "UC-OpenAPI-OAuth" \
  --master "local[*]" \
  --packages "io.delta:delta-spark_2.13:4.0.1,io.unitycatalog:unitycatalog-spark_2.13:0.3.1,org.apache.hadoop:hadoop-aws:3.4.0" \
  --conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension" \
  --conf "spark.sql.catalog.spark_catalog=io.unitycatalog.spark.UCSingleCatalog" \
  --conf "spark.hadoop.fs.s3.impl=org.apache.hadoop.fs.s3a.S3AFileSystem" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;=io.unitycatalog.spark.UCSingleCatalog" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.uri=https://&amp;lt;&amp;lt;Your Databricks Workspace URL&amp;gt;&amp;gt;" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.auth.type=oauth" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.auth.oauth.uri=https://&amp;lt;&amp;lt;Your Databricks Workspace URL&amp;gt;&amp;gt;/oidc/v1/token" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.auth.oauth.clientId=&amp;lt;&amp;lt;ClientID from Your OAuth secret&amp;gt;&amp;gt;" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.auth.oauth.clientSecret=&amp;lt;&amp;lt;ClientSecret from Your OAuth secret&amp;gt;&amp;gt;" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.renewCredential.enabled=true" \
  --conf "spark.sql.defaultCatalog=&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;"&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&lt;SPAN&gt;Note the following items in this command:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;--packages&lt;/SPAN&gt;&lt;SPAN&gt; points to the &lt;/SPAN&gt;&lt;SPAN&gt;delta-spark&lt;/SPAN&gt;&lt;SPAN&gt; and &lt;/SPAN&gt;&lt;SPAN&gt;unitycatalog-spark&lt;/SPAN&gt;&lt;SPAN&gt; packages.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;spark.sql.defaultCatalog=&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN&gt; must be filled out to indicate the default catalog you want to use when launching the &lt;/SPAN&gt;&lt;SPAN&gt;spark-sql&lt;/SPAN&gt;&lt;SPAN&gt; shell.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.uri&lt;/SPAN&gt;&lt;SPAN&gt; points to the Databricks UC REST API endpoint for the workspace.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.auth.oauth.clientId and spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.auth.oauth.clientSecret&lt;/SPAN&gt;&lt;SPAN&gt; are your &lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/aws/en/dev-tools/auth/oauth-m2m" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Client ID and Client Secret for M2M OAuth authorization&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;. They are used to authenticate the principal as a legitimate user to the Databricks platform. &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;Access to the UC objects is controlled via the UC permissions model&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;spark.hadoop.fs.s3.impl=org.apache.hadoop.fs.s3a.S3AFileSystem&lt;SPAN&gt; must be set to access your cloud object storage (in this example, AWS S3).&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;Now you’re ready to perform operations using Spark SQL in Databricks UC.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H4&gt;&lt;SPAN&gt;Accessing Databricks UC from the PySpark shell&lt;/SPAN&gt;&lt;/H4&gt;
&lt;P&gt;&lt;SPAN&gt;To use the PySpark shell (&lt;/SPAN&gt;&lt;SPAN&gt;bin/pyspark&lt;/SPAN&gt;&lt;SPAN&gt;), go into the &lt;/SPAN&gt;&lt;SPAN&gt;bin&lt;/SPAN&gt;&lt;SPAN&gt; folder inside your downloaded Apache Spark folder (&lt;/SPAN&gt;&lt;SPAN&gt;spark-4.0.1-bin-hadoop3&lt;/SPAN&gt;&lt;SPAN&gt;) in your terminal:&lt;/SPAN&gt;&lt;/P&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="python"&gt;cd spark-4.0.1-bin-hadoop3/bin&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&lt;SPAN&gt;Once you’re inside the &lt;/SPAN&gt;&lt;SPAN&gt;bin&lt;/SPAN&gt;&lt;SPAN&gt; folder, run the following command to launch the &lt;/SPAN&gt;&lt;SPAN&gt;pyspark&lt;/SPAN&gt;&lt;SPAN&gt; shell (see the previous section for a discussion of the packages and configuration options):&lt;/SPAN&gt;&lt;/P&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="python"&gt;./pyspark --name "UC-OpenAPI-OAuth" \
  --master "local[*]" \
  --packages "io.delta:delta-spark_2.13:4.0.1,io.unitycatalog:unitycatalog-spark_2.13:0.3.1,org.apache.hadoop:hadoop-aws:3.4.0" \
  --conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension" \
  --conf "spark.sql.catalog.spark_catalog=io.unitycatalog.spark.UCSingleCatalog" \
  --conf "spark.hadoop.fs.s3.impl=org.apache.hadoop.fs.s3a.S3AFileSystem" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;=io.unitycatalog.spark.UCSingleCatalog" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.uri=https://&amp;lt;&amp;lt;Your Databricks Workspace URL&amp;gt;&amp;gt;" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.auth.type=oauth" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.auth.oauth.uri=https://&amp;lt;&amp;lt;Your Databricks Workspace URL&amp;gt;&amp;gt;/oidc/v1/token" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.auth.oauth.clientId=&amp;lt;&amp;lt;ClientID from Your OAuth secret&amp;gt;&amp;gt;" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.auth.oauth.clientSecret=&amp;lt;&amp;lt;ClientSecret from Your OAuth secret&amp;gt;&amp;gt;" \
  --conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.renewCredential.enabled=true" \
  --conf "spark.sql.defaultCatalog=&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;"
&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&lt;SPAN&gt;Now you’re ready to perform operations using PySpark in Databricks UC.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN&gt;Step 3: Performing CRUD operations on Delta tables in Databricks UC from the local terminal&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;I&lt;/SPAN&gt;&lt;SPAN&gt;n this step, I’ll walk you through performing some CRUD operations on Databricks UC tables. I’ll use Spark SQL here, but the same SQL commands can be run in the PySpark shell by embedding them in&lt;/SPAN&gt;&lt;SPAN&gt; spark.sql()&lt;/SPAN&gt;&lt;SPAN&gt;. You can also use PySpark DataFrame APIs to perform DML (Data Manipulation Language) operations on the Databricks UC tables.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Here are some of the commands you can run inside the spark-sql shell, including example output for some of them:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;See all the accessible UC catalogs:&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="python"&gt;SHOW CATALOGS;&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;SPAN&gt;See all the available schemas in the default (&lt;/SPAN&gt;&lt;SPAN&gt;&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN&gt;) catalog you used when launching the &lt;/SPAN&gt;&lt;SPAN&gt;spark-sql&lt;/SPAN&gt;&lt;SPAN&gt; shell:&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="python"&gt;SHOW SCHEMAS;&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_0-1770409472761.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23719iF78A93FF53F18E1F/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_0-1770409472761.png" alt="dkushari_0-1770409472761.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Create a new schema:&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%" height="82px"&gt;&lt;LI-CODE lang="python"&gt;CREATE SCHEMA db_schema;&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Use this new schema as the default schema:&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="python"&gt;USE SCHEMA db_schema;&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Create a new external table:&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="python"&gt;CREATE external TABLE
db_uc_table (id INT, desc STRING)
USING DELTA
LOCATION 's3://&amp;lt;&amp;lt;Your AWS S3 Location&amp;gt;&amp;gt;';
&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Describe the newly created table:&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%" height="63px"&gt;&lt;LI-CODE lang="python"&gt;DESC EXTENDED db_uc_table;&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_1-1770409636864.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23720iA40DC0872C421FEB/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_1-1770409636864.png" alt="dkushari_1-1770409636864.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;For comparison, here’s how this information looks like in the Databricks workspace:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_2-1770409667197.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23721i2BA3A9E97AE191A8/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_2-1770409667197.png" alt="dkushari_2-1770409667197.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_3-1770409737270.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23722i084FFFBC18A12A82/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_3-1770409737270.png" alt="dkushari_3-1770409737270.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Insert some records from the local terminal into the newly created table and select from that table:&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="python"&gt;INSERT INTO db_uc_table VALUES (1,'a'),(2,'b'), (3,'c'),(4,'d'),(5,'e');
&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%" height="62px"&gt;&lt;LI-CODE lang="python"&gt;SELECT * FROM db_uc_table ORDER BY id;&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_3-1770410233348.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23729iE750F0B61B97EF48/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_3-1770410233348.png" alt="dkushari_3-1770410233348.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Here’s what you’ll see if you explore the same table from the Databricks workspace:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_4-1770410306300.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23730i73E995C916F38ED3/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_4-1770410306300.png" alt="dkushari_4-1770410306300.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_5-1770410360125.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23731iFB70DBD8E57B63A1/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_5-1770410360125.png" alt="dkushari_5-1770410360125.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_6-1770410403825.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23732i4611F60FA70DA815/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_6-1770410403825.png" alt="dkushari_6-1770410403825.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Next, let’s create a new managed table in the same UC catalog and schema from the Databricks workspace and read it from the local terminal. Here’s what you’ll see in the &lt;/SPAN&gt;&lt;SPAN&gt;spark-sql&lt;/SPAN&gt;&lt;SPAN&gt; shell before the managed table is created:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_7-1770410441213.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23733i4FE5CDF9EA8D3F40/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_7-1770410441213.png" alt="dkushari_7-1770410441213.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Now, create the managed Delta table from the local terminal. Then run the &lt;/SPAN&gt;&lt;SPAN&gt;show tables&lt;/SPAN&gt;&lt;SPAN&gt; command again from the local terminal. Now the managed table is in the list:&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;CREATE TABLE db_uc_table_managed (id INT, desc STRING) USING delta TBLPROPERTIES ('delta.feature.catalogManaged'='supported');&lt;/LI-CODE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_8-1770410588510.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23734i5968B8EA0B8AC893/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_8-1770410588510.png" alt="dkushari_8-1770410588510.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_9-1770410642015.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23735i3AD7972A88B432D3/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_9-1770410642015.png" alt="dkushari_9-1770410642015.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;You can insert data into the managed table from both the local terminal and the Databricks workspace. First, insert and select some data from the local terminal:&lt;/SPAN&gt;&lt;/P&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="python"&gt;INSERT INTO db_uc_table_managed VALUES (1,'a');
SELECT * FROM db_uc_table_managed;&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_10-1770410753503.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23736i12D558168095B33D/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_10-1770410753503.png" alt="dkushari_10-1770410753503.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;You can select the same data from the Databricks workspace:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_11-1770410813949.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23737i35C064F71A4973E3/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_11-1770410813949.png" alt="dkushari_11-1770410813949.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;And here we are inserting data into the managed table from the Databricks workspace:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_12-1770410837937.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23738i89A90CC5A6DBD81C/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_12-1770410837937.png" alt="dkushari_12-1770410837937.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Here’s another example of selecting data from the managed table from both the local terminal and the Databricks workspace:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_13-1770410866702.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23739iE1E3FB0FD60E6108/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_13-1770410866702.png" alt="dkushari_13-1770410866702.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_14-1770410904228.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23740i8D9821E64D0DF316/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_14-1770410904228.png" alt="dkushari_14-1770410904228.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Now let’s try performing some upsert activities on the external table from the local terminal and the Databricks workspace. First, let's perform a delete activity on the external table from the local terminal: &lt;/SPAN&gt;&lt;/P&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="python"&gt;DELETE FROM db_uc_table WHERE id IN (1, 3);&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&lt;SPAN&gt;Here we are selecting data from the external table from the local terminal and the Databricks workspace, and notice that 2 rows have been deleted:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_15-1770411022198.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23741iCC81D1E94D16887D/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_15-1770411022198.png" alt="dkushari_15-1770411022198.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_18-1770411144897.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23744i465D84DCAADDEAE9/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_18-1770411144897.png" alt="dkushari_18-1770411144897.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Next, let's perform an update activity on the managed table from the Databricks workspace:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_19-1770411244624.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23745iC3E0D168F350C5DC/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_19-1770411244624.png" alt="dkushari_19-1770411244624.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;UPDATE db_uc_table_managed SET desc = 'f' WHERE id = 3;&lt;/LI-CODE&gt;
&lt;P&gt;&lt;SPAN&gt;And select the data from the managed table using the local terminal. You can notice the change reflected for the record with id = 3:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_20-1770411331566.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23746iF400F66D8EAF5BF0/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_20-1770411331566.png" alt="dkushari_20-1770411331566.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_21-1770411349572.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23747iE8B75C0C67FF8EC7/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_21-1770411349572.png" alt="dkushari_21-1770411349572.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;We can show the history of changes to the managed table, due to DML operations, from the Databricks workspace UI:&lt;/SPAN&gt;&lt;/P&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_22-1770411436859.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23748iFFCC42378A5DD006/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_22-1770411436859.png" alt="dkushari_22-1770411436859.png" /&gt;&lt;/span&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;DESC HISTORY db_uc_table_managed;&lt;/LI-CODE&gt;
&lt;H3&gt;&lt;SPAN&gt;Step 4: Performing a UC access control test&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Next, let’s run a quick test to verify that access control is working as expected. To perform this test, we’re going to make a change to the UC permissions for the Databricks authenticated user who is accessing the &lt;/SPAN&gt;&lt;SPAN&gt;spark-sq&lt;/SPAN&gt;&lt;SPAN&gt;l shell from the local terminal. Namely, we’ll remove their access to the UC object (i.e., the External Delta table, namely&lt;/SPAN&gt;&lt;SPAN&gt; db_uc_table&lt;/SPAN&gt;&lt;SPAN&gt;) we’ve been working with.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Let's change the owner of the external Delta table to another user. This means that the user whose credentials are used from the &lt;/SPAN&gt;&lt;SPAN&gt;spark-sq&lt;/SPAN&gt;&lt;SPAN&gt;l shell of the local terminal to access the UC data no longer has &lt;/SPAN&gt;&lt;SPAN&gt;SELECT&lt;/SPAN&gt;&lt;SPAN&gt; permission on the table.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_23-1770411555702.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23749iBB4042CD173E955D/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_23-1770411555702.png" alt="dkushari_23-1770411555702.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_24-1770411573021.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23750i49802D7161CA4F16/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_24-1770411573021.png" alt="dkushari_24-1770411573021.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;This query from the local terminal fails with permission denied, as expected:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_25-1770411612186.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23751iB0BD4D474DDEC74B/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_25-1770411612186.png" alt="dkushari_25-1770411612186.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;This shows that the user who was authenticated via Databricks M2M OAuth also requires proper UC authorization to access data governed by Unity Catalog. Without the proper UC permission, access to the UC object will be denied.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN&gt;Step 5: Performing CRUD operations on Managed Iceberg tables in Databricks UC from the local terminal&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;You can perform CRUD operations on &lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/aws/en/tables/managed" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Managed Iceberg tables&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt; from Databricks Unity Catalog through the Iceberg REST Catalog (IRC) API. This allows you to access these tables from any client that supports Iceberg REST Catalog APIs without introducing new dependencies.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;To access Managed Iceberg tables in Databricks UC from the local terminal, enter the following command to launch the &lt;/SPAN&gt;&lt;SPAN&gt;spark-sq&lt;/SPAN&gt;&lt;SPAN&gt;l shell:&lt;/SPAN&gt;&lt;/P&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="python"&gt;./spark-sql --name "uc-iceberg-oauth" \
    --master "local[*]" \
    --packages "org.apache.iceberg:iceberg-spark-runtime-4.0_2.13:1.10.1,org.apache.iceberg:iceberg-aws-bundle:1.6.1,io.unitycatalog:unitycatalog-spark_2.13:0.3.1,io.delta:delta-spark_2.13:4.0.1" \
    --conf "spark.hadoop.fs.s3.impl=org.apache.iceberg.aws.s3.S3FileIO" \
    --conf "spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions" \
    --conf "spark.sql.catalog.iceberg=org.apache.iceberg.spark.SparkCatalog" \
    --conf "spark.sql.catalog.iceberg.catalog-impl=org.apache.iceberg.rest.RESTCatalog" \
    --conf "spark.sql.catalog.iceberg.uri=https://&amp;lt;&amp;lt;Your Databricks Workspace URL&amp;gt;&amp;gt;/api/2.1/unity-catalog/iceberg-rest" \
    --conf "spark.sql.catalog.iceberg.oauth2-server-uri=https://&amp;lt;&amp;lt;Your Databricks Workspace URL&amp;gt;&amp;gt;/oidc/v1/token" \
    --conf "spark.sql.catalog.iceberg.scope=all-apis" \
    --conf "spark.sql.catalog.iceberg.credential=&amp;lt;&amp;lt;ClientID from Your OAuth secret&amp;gt;&amp;gt;:&amp;lt;&amp;lt;ClientSecret from Your OAuth secret&amp;gt;&amp;gt;" \
    --conf "spark.sql.defaultCatalog=iceberg" \
    --conf "spark.sql.catalog.iceberg.warehouse=&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;"&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&lt;SPAN&gt;Let’s create a Managed Iceberg table from the local terminal and view its details.&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;USE db_schema;
SHOW TABLES;
CREATE TABLE db_uc_table_managed_ib (id INT, desc STRING) USING ICEBERG;
SHOW TABLES;
DESC EXTENDED db_uc_table_managed_ib;
&lt;/LI-CODE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_26-1770412050123.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23752iCD8815872F8DC87D/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_26-1770412050123.png" alt="dkushari_26-1770412050123.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Now, let's insert some rows into the Managed Iceberg table from the local terminal:&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;INSERT INTO db_uc_table_managed_ib VALUES (1, 'a'), (2,'b'), (3,'c'),(4,'d'),(5,'e');&lt;/LI-CODE&gt;
&lt;P&gt;&lt;SPAN&gt;Here’s what we’ll see in the local terminal when we select rows from the Managed Iceberg table:&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;SELECT * FROM db_uc_table_managed_ib ORDER BY id;&lt;/LI-CODE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_27-1770412135944.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23753i0C56FE145EDCA7A4/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_27-1770412135944.png" alt="dkushari_27-1770412135944.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;We can also read the same Managed Iceberg table from the Databricks workspace:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_28-1770412174401.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23754iF360AD205FC45A19/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_28-1770412174401.png" alt="dkushari_28-1770412174401.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Let’s update the Managed Iceberg table and read from it again. Here’s the query we ran to update the table (as usual, you can enter this in the local terminal or the Databricks workspace, as shown here) from the local terminal:&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;UPDATE db_uc_table_managed_ib SET desc = 'updated' where id = 5;&lt;/LI-CODE&gt;
&lt;P&gt;&lt;SPAN&gt;And here’s what we see when we read from the table:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_29-1770412221266.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23755i1ADA34A7DD95F734/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_29-1770412221266.png" alt="dkushari_29-1770412221266.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_30-1770412252750.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23756iE6FD7966CA130001/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_30-1770412252750.png" alt="dkushari_30-1770412252750.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN&gt;Step 6: Accessing UniForm Iceberg tables in Databricks UC from the local terminal&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Using the &lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/aws/en/tables/managed#access-databricks-data-using-external-systems" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Iceberg REST Catalog (IRC) API &lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;from the local terminal, we can also read the &lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/aws/en/delta/uniform" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;UniForm Iceberg tables&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;, created from the Databricks workspace. Here is an example:&lt;/SPAN&gt;&lt;/P&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;LI-CODE lang="python"&gt;CREATE TABLE iceberg_ext_tab(id INT, desc STRING)
location "s3://&amp;lt;&amp;lt;Your AWS S3 Location&amp;gt;&amp;gt;"
TBLPROPERTIES(
'delta.enableIcebergCompatV2' = 'true',
'delta.universalFormat.enabledFormats' = 'iceberg');

INSERT INTO iceberg_ext_tab VALUES (1, 'a'), (2,'b'), (3,'c'),(4,'d'),(5,'e');

DESC EXTENDED iceberg_ext_tab;

SELECT * FROM iceberg_ext_tab ORDER BY id;&lt;/LI-CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_31-1770412331537.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23757iF70156495B062CEC/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_31-1770412331537.png" alt="dkushari_31-1770412331537.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;TABLE style="border-style: hidden; width: 100%;" border="1" width="100%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="100%"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_32-1770412370803.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23758i000BAE93639F9E38/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_32-1770412370803.png" alt="dkushari_32-1770412370803.png" /&gt;&lt;/span&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_33-1770412399718.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/23759i9AAAEB174F886DEA/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_33-1770412399718.png" alt="dkushari_33-1770412399718.png" /&gt;&lt;/span&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;H2&gt;&lt;SPAN&gt;Conclusion&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;This blog showed you how to use Apache Spark from an external (non-Databricks) processing engine to securely perform CRUD operations on your Delta and Managed Iceberg tables registered in a Databricks Unity Catalog metastore, using UC’s open source REST APIs and Iceberg REST Catalog (IRC) APIs. We also looked at how you can read your UniForm Iceberg tables registered in Databricks UC using the Iceberg REST Catalog (IRC) API. Try out Unity Catalog’s Open APIs and Iceberg REST Catalog (IRC) APIs today to access and process your data securely from any external engine using Apache Spark.&lt;/SPAN&gt;&lt;/P&gt;</description>
    <pubDate>Fri, 05 Jun 2026 09:19:34 GMT</pubDate>
    <dc:creator>dkushari</dc:creator>
    <dc:date>2026-06-05T09:19:34Z</dc:date>
    <item>
      <title>Integrating Apache Spark™ with Databricks Unity Catalog Assets via Open APIs</title>
      <link>https://community.databricks.com/t5/technical-blog/integrating-apache-spark-with-databricks-unity-catalog-assets/ba-p/97533</link>
      <description>&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="dkushari_36-1730725387176.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/12610iF85D5580C6C1B3E8/image-size/large?v=v2&amp;amp;px=999" role="button" title="dkushari_36-1730725387176.png" alt="dkushari_36-1730725387176.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 05 Jun 2026 09:19:34 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/integrating-apache-spark-with-databricks-unity-catalog-assets/ba-p/97533</guid>
      <dc:creator>dkushari</dc:creator>
      <dc:date>2026-06-05T09:19:34Z</dc:date>
    </item>
    <item>
      <title>Re: Integrating Apache Spark™ with Databricks Unity Catalog Assets via Open APIs</title>
      <link>https://community.databricks.com/t5/technical-blog/integrating-apache-spark-with-databricks-unity-catalog-assets/bc-p/101989#M413</link>
      <description>&lt;P&gt;This looks exactly like what I've been hoping for! However, the tutorial as shown here doesn't seem to work for me.&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;The repo &lt;A href="https://s01.oss.sonatype.org/content/repositories/iounitycatalog-1016/`" target="_blank"&gt;https://s01.oss.sonatype.org/content/repositories/iounitycatalog-1016/&lt;/A&gt; does not exist and 404s. Luckily, unitycatalog-spark is published elsewhere on sonatype&lt;/LI&gt;&lt;LI&gt;There seems to be a version mismatch in the dependent hadoop libraries.&lt;UL&gt;&lt;LI&gt;Spark 3.5.{0-3} are all compiled against hadoop 3.3.4.&lt;/LI&gt;&lt;LI&gt;unitycatalog-spark versions 0.2.{0,1} depend on spark 3.5.3.&lt;/LI&gt;&lt;LI&gt;unitycatalog-spark also depend on &lt;A href="https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-client-runtime" target="_blank"&gt;hadoop-client-runtime&lt;/A&gt; 3.4.0&lt;/LI&gt;&lt;LI&gt;hadoop libraries 3.4.0 have an updated FSBuilder that has an `optLong` method that is not present in 3.3.4. This results in `java.lang.NoSuchMethodError` if this tutorial is attempted with spark 3.3.4 and `java.lang.NumberFormatException` if upgraded to 3.4.0.&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;Is this tutorial possible or was unitycatalog-spark released with incompatible dependencies? Thanks!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 12 Dec 2024 21:11:29 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/integrating-apache-spark-with-databricks-unity-catalog-assets/bc-p/101989#M413</guid>
      <dc:creator>Klugscheißer</dc:creator>
      <dc:date>2024-12-12T21:11:29Z</dc:date>
    </item>
    <item>
      <title>Re: Integrating Apache Spark™ with Databricks Unity Catalog Assets via Open APIs</title>
      <link>https://community.databricks.com/t5/technical-blog/integrating-apache-spark-with-databricks-unity-catalog-assets/bc-p/102122#M417</link>
      <description>&lt;P&gt;I was able to resolve the above dependency issues by explicitly depending on hadoop-aws 3.4.1 in addition to `&lt;SPAN&gt;spark-hadoop-cloud` &lt;/SPAN&gt;and was able to read and write to tables in UC from OSS spark!&lt;/P&gt;&lt;P&gt;However, I'm now having difficulty with the Uniform part. If I only add a dependency on `iceberg-spark-runtime-3.5`, then writing to a Uniform iceberg table fails with&lt;/P&gt;&lt;PRE&gt;ERROR org.apache.spark.sql.delta.DeltaLog - Failed to find Iceberg converter class&lt;BR /&gt;java.lang.ClassNotFoundException: org.apache.spark.sql.delta.icebergShaded.IcebergConverter&lt;/PRE&gt;&lt;P&gt;If I add `delta-iceberg` then the IcebergConverter class is found, reading and writing to the table works, however the iceberg conversion on write fails with&lt;/P&gt;&lt;PRE&gt;ERROR org.apache.spark.sql.delta.icebergShaded.IcebergConverter - Error when converting to Iceberg metadata&lt;BR /&gt;org.apache.spark.sql.catalyst.analysis.NoSuchDatabaseException: [SCHEMA_NOT_FOUND] The schema `test_schema` cannot be found. Verify the spelling and correctness of the schema and catalog.&lt;BR /&gt;[info] If you did not qualify the name with a catalog, verify the current_schema() output, or qualify the name with the correct catalog.&lt;/PRE&gt;&lt;P&gt;Possibly related, while `SHOW SCHEMAS` does list the `test_schema` I've been using and `SELECT current_schema()` does indeed return `test_schema`, `spark.sessionState.catalog.listDatabases()` does not! Reading the &lt;A href="https://github.com/delta-io/delta/blob/c8697c5897e63d64be1a3f79dc292f930de8e333/iceberg/src/main/scala/org/apache/spark/sql/delta/icebergShaded/IcebergConverter.scala#L274C61-L274C71" target="_self"&gt;code&lt;/A&gt;, it seems like this is what's referenced during the iceberg conversion. It's not clear to me why the schema / db is not consistent across various spark calls.&lt;/P&gt;</description>
      <pubDate>Fri, 13 Dec 2024 21:39:34 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/integrating-apache-spark-with-databricks-unity-catalog-assets/bc-p/102122#M417</guid>
      <dc:creator>Klugscheißer</dc:creator>
      <dc:date>2024-12-13T21:39:34Z</dc:date>
    </item>
    <item>
      <title>Re: Integrating Apache Spark™ with Databricks Unity Catalog Assets via Open APIs</title>
      <link>https://community.databricks.com/t5/technical-blog/integrating-apache-spark-with-databricks-unity-catalog-assets/bc-p/141506#M854</link>
      <description>&lt;P&gt;That's a great article, thanks for sharing! It perfectly aligns with our requirement for a more &lt;STRONG&gt;open&lt;/STRONG&gt; approach.&lt;/P&gt;&lt;P&gt;However, I have a follow-up question regarding &lt;STRONG&gt;Access Tokens from Entra&lt;/STRONG&gt; for &lt;STRONG&gt;Databricks&lt;/STRONG&gt; authentication to &lt;STRONG&gt;Unity Catalog&lt;/STRONG&gt; when running &lt;STRONG&gt;Spark on Kubernetes (K8s)&lt;/STRONG&gt;.&lt;/P&gt;&lt;P&gt;Specifically, I'm encountering an issue with &lt;STRONG&gt;long-running tasks (over 1 hour)&lt;/STRONG&gt;:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;&lt;STRONG&gt;How can I configure the Spark session to automatically refresh these tokens?&lt;/STRONG&gt;&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;</description>
      <pubDate>Tue, 09 Dec 2025 12:58:50 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/integrating-apache-spark-with-databricks-unity-catalog-assets/bc-p/141506#M854</guid>
      <dc:creator>sparkplug</dc:creator>
      <dc:date>2025-12-09T12:58:50Z</dc:date>
    </item>
    <item>
      <title>Re: Integrating Apache Spark™ with Databricks Unity Catalog Assets via Open APIs</title>
      <link>https://community.databricks.com/t5/technical-blog/integrating-apache-spark-with-databricks-unity-catalog-assets/bc-p/142017#M862</link>
      <description>&lt;DIV&gt;Could you clarify how you are leveraging credential vending? I noticed that the blog post appears to use the Databricks PAT directly, and I didn’t see credential vending mentioned. Could you please explain?&lt;/DIV&gt;&lt;P&gt;=====&lt;BR /&gt;&lt;SPAN&gt;With its open APIs and introduction of credential vending, Databricks Unity Catalog data can be read by external engines and interfaces such as Iceberg REST APIs, DuckDB, Apache Spark™, Trino.&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;PRE&gt;/spark-sql --name "s3-uc-test" \
	--master "local[*]" \
	--packages "org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:1.6.1,io.delta:delta-spark_2.12:3.2.1,io.unitycatalog:unitycatalog-spark_2.12:0.2.0,org.apache.hadoop:hadoop-common:3.3.4,org.apache.hadoop:hadoop-aws:3.3.4" \
	--conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension" \
	--conf "spark.sql.catalog.spark_catalog=io.unitycatalog.spark.UCSingleCatalog" \
	--conf "spark.hadoop.fs.s3.impl=org.apache.hadoop.fs.s3a.S3AFileSystem" \
	--conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;=io.unitycatalog.spark.UCSingleCatalog" \
	--conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.uri=https://&amp;lt;&amp;lt;Your Databricks Workspace URL&amp;gt;&amp;gt;/api/2.1/unity-catalog" \
	--conf "spark.sql.catalog.&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;.token=&amp;lt;&amp;lt;Your Databricks Workspace PAT&amp;gt;&amp;gt;" \
	--conf "spark.sql.defaultCatalog=&amp;lt;&amp;lt;Your Default UC Catalog&amp;gt;&amp;gt;"&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 16 Dec 2025 18:13:19 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/integrating-apache-spark-with-databricks-unity-catalog-assets/bc-p/142017#M862</guid>
      <dc:creator>dbx_8451</dc:creator>
      <dc:date>2025-12-16T18:13:19Z</dc:date>
    </item>
  </channel>
</rss>

