TL;DR
Databricks CREATE TABLE has seven usable forms, and the grammar is the easy part. What actually matters is the decision made before the DDL runs: managed or external, CTAS or clone, liquid clustering or partitioning, REPLACE or drop. Pick those correctly and the table stays cheap to store, easy to govern, and safe to redeploy.
Key Takeaways Omit USING and Databricks CREATE TABLE builds a managed Delta table , which is the right default for almost every new table in Unity Catalog. Adding a LOCATION clause turns the same statement into an external table and moves storage lifecycle, file cleanup, and automatic optimization onto your team permanently. Databricks strongly recommends CREATE OR REPLACE over dropping and recreating, because REPLACE preserves table history, granted privileges, row filters, and column masks. Liquid clustering has replaced PARTITIONED BY as the default layout advice, and the two clauses cannot be combined in a single table definition. Most CREATE TABLE failures map to a named Databricks error condition, and the condition name points at the fix faster than the stack trace does. Kanerika, a Databricks Consulting Partner, standardized table design on a healthcare Informatica to Databricks migration that delivered 71% higher reporting accuracy. The Table That Worked Fine Until Someone Cleaned Up a Storage Bucket A data engineer ships a nightly pipeline. The CREATE TABLE statement carries a LOCATION clause pointing at an existing cloud storage prefix, because that is what the tutorial they copied had. It runs, the pipeline loads, dashboards light up, and nobody looks at it again.
Eight months later a platform cleanup job reclaims what looks like an unused prefix. The table still exists in Unity Catalog. Every query against it now returns nothing, because Unity Catalog never owned those files and never had a vote in deleting them.
Nothing in that statement was syntactically wrong. Databricks accepted it without a warning. The mistake was a decision, not a typo, and it was made inside a single clause the engineer did not know was a decision at all.
That is the gap this guide fills. The Databricks SQL reference documents every clause precisely and says almost nothing about which one you should reach for. What follows is the decision layer: seven ways to create a table on Databricks , when each one wins, and how to read the failures when it does not work.
Watch on YouTube
Databricks Unity Catalog Explained
A walkthrough of Unity Catalog, the three-level namespace your CREATE TABLE statement writes into and the layer that decides managed versus external behaviour.
The Shortest Databricks CREATE TABLE That Actually Works The minimum viable statement in Unity Catalog is a three-part name, a column list, and nothing else. Everything past that point is an optional decision, not a requirement, though the column list itself is where data modeling discipline pays for itself.
CREATE TABLE main.sales.orders (
order_id BIGINT NOT NULL COMMENT 'Source system order key',
customer_id BIGINT NOT NULL,
order_ts TIMESTAMP,
order_total DECIMAL(18,2),
status STRING
)
COMMENT 'Cleaned order headers from the OMS feed';That statement creates a managed Delta table. Databricks documents the rule plainly: if USING is omitted, the default is DELTA. You do not need to write USING DELTA, and most production DDL in well-run workspaces does not.
The three-part name main.sales.orders is the Unity Catalog namespace: catalog, then schema, then table, resolved by the Unity Catalog metastore attached to your workspace. Skipping the catalog and schema is the fastest way to create an object somewhere you did not intend, which is why qualified names belong in every deployed script.
The optional clauses cluster into a small set of jobs. Knowing which job each one does is most of the battle.
Table 1: What each CREATE TABLE clause actually decides
Clause What it decides Change it later? USINGTable format or federated source. Omit for Delta. No, requires a rebuild LOCATIONManaged or external. Storage lifecycle ownership. No, requires a migration CLUSTER BY / PARTITIONED BYPhysical data layout for read pruning. Clustering keys yes, partitioning no TBLPROPERTIESDelta behavior: retention, change feed, column mapping. Some yes, several are one-way MASK / WITH ROW FILTERWho sees which rows and columns. Yes, via ALTER TABLE AS query (CTAS)Schema is inferred from the query, not declared. Not applicable
One footnote that catches teams registering raw files: for any format other than Delta or Iceberg, leaving out both LOCATION and AS query produces a managed table with no data in it. The statement succeeds and the table is empty.
Managed or External? The Clause That Decides Who Owns Your Data Adding a LOCATION makes the table external. That single clause moves storage lifecycle, file cleanup, and automatic optimization off Databricks and onto your team, permanently. It is the most consequential decision in the whole statement and the one most guides describe without ever framing as a choice, even though it shapes the entire lakehouse architecture underneath.
-- Managed: Databricks owns the storage path
CREATE TABLE main.sales.orders (order_id BIGINT, order_total DECIMAL(18,2));
-- External: you own the path, and everything that happens to it
CREATE EXTERNAL TABLE main.sales.orders_raw (order_id BIGINT, order_total DECIMAL(18,2))
LOCATION 's3://acme-lake/raw/orders/';The behavioral split shows up hardest at drop time and at optimization time. Databricks supports UNDROP TABLE for managed tables, with a default seven-day recovery window before the underlying files are deleted. Drop an external table and Unity Catalog removes the metadata while leaving every file exactly where it was.
Table 2: Managed vs external tables, decided rather than defined
Decision point Managed table External table Storage lifecycle owner Unity Catalog Your cloud team On DROP TABLE Recoverable via UNDROP for 7 days, then files removed Metadata gone, files untouched and unbilled by Databricks Predictive optimization Available, on by default for newer accounts Not available Automatic liquid clustering Available with CLUSTER BY AUTO Not available Migration cost to switch later Low, deep clone into a new external path High, files and downstream readers both move When it is the right call Almost every new analytical table Data another engine writes, or a path compliance requires you to control
Databricks names a specific list of capabilities as managed-table-only, including predictive optimization, automatic liquid clustering, multi-statement transactions, and metadata caching. Choosing external is choosing to opt out of all of them at once.
The practical rule is narrow. Reach for external when another engine genuinely owns the write path, when a regulator or contract requires files in a bucket you control, or when a legacy consumer reads the raw files directly. Everything else belongs in a managed table, a stance that Unity Catalog design guidance and the official managed-table documentation both take.
Seven Ways to Create a Databricks Table Seven forms cover essentially every real creation task. They differ in what they copy, what they infer, and what they preserve.
Explicit schema. You declare every column and type. Best for tables with a contract that downstream systems depend on.External registration with LOCATION. Points the catalog at files that already exist. For files that keep arriving, Auto Loader is the right pattern instead.CTAS. CREATE TABLE ... AS SELECT materializes a query result and infers the schema from it. For a refreshing derivation, materialized views are usually the better tool.CREATE TABLE LIKE . Copies a definition without a single row of data.DEEP CLONE. Copies data and metadata into an independent table.SHALLOW CLONE. Copies metadata only and keeps pointing at the source files.CREATE OR REPLACE. Redefines an existing table in place while keeping what surrounds it.-- 3. CTAS: schema comes from the query, so cast deliberately
CREATE TABLE main.sales.orders_2026 AS
SELECT order_id,
customer_id,
CAST(order_total AS DECIMAL(18,2)) AS order_total
FROM main.sales.orders
WHERE order_ts >= '2026-01-01';
-- 5. DEEP CLONE: independent copy, keeps partitioning and metadata
CREATE TABLE main.sales.orders_backup DEEP CLONE main.sales.orders;
-- 6. SHALLOW CLONE: instant, cheap, still tied to the source files
CREATE TABLE main.dev.orders_test SHALLOW CLONE main.sales.orders;An eighth form exists for scratch work. Session-local temporary tables arrived in Databricks Runtime 18.1 and above, use an unqualified name with no catalog or schema, and refuse most of the interesting clauses. USING, LOCATION, PARTITIONED BY, CLUSTER BY, generated columns, row filters, and column masks are all unsupported on them.
CTAS, CLONE, or LIKE? The Three Get Confused Constantly All three produce a new table from an existing one, which is why teams treat them as interchangeable. They are not. The difference is in what silently does not come along.
CTAS is the common trap. It infers the target schema from the query, so nullability, precision, and column comments are whatever the SELECT happened to produce. A deep clone, by contrast, carries partitioning, clustering, and table metadata across intact.
Table 3: Picking between CTAS, CLONE, and LIKE
Question CTAS DEEP CLONE CREATE TABLE LIKE Copies the rows? Only what the query returns Yes, all of them No Keeps layout and metadata? No, inferred fresh Yes Definition only Can you transform on the way? Yes, that is the point No No Storage cost of the copy Full Full None Use it for Curated or filtered derivations Backups, environment promotion, archives Empty staging twins
Deep clone is also the cleanest way to promote a table between environments without rerunning an ETL pipeline . Shallow clone deserves its own caution. It is instant and free because it copies no files, which makes it excellent for a throwaway test table and dangerous as anything permanent, since vacuuming the source can break it.
Kanerika Service
Databricks Consulting and Implementation
Kanerika is a Databricks Consulting Partner that designs Unity Catalog structures, table standards, and governed data platforms for enterprise teams, from first schema to production migration.
Explore Databricks Services The Same Table, Four Ways: SQL, PySpark, DeltaTableBuilder, and the UI Databricks offers four entry points to the same object. Guides usually cover them in separate sections with different example tables, which hides how identical the outcome is. Here is one table built four ways.
-- 1. SQL DDL
CREATE TABLE main.sales.orders (
order_id BIGINT NOT NULL,
order_total DECIMAL(18,2)
) CLUSTER BY (order_id);# 2. PySpark DataFrameWriter
(df.write
.format("delta")
.mode("overwrite")
.clusterBy("order_id")
.saveAsTable("main.sales.orders"))# 3. DeltaTableBuilder API
from delta.tables import DeltaTable
(DeltaTable.createIfNotExists(spark)
.tableName("main.sales.orders")
.addColumn("order_id", "BIGINT", nullable=False)
.addColumn("order_total", "DECIMAL(18,2)")
.clusterBy("order_id")
.execute())The saveAsTable reference covers the DataFrame variant in full. The fourth path is Catalog Explorer. Choosing a schema, clicking Create, and uploading a file registers a real Unity Catalog table with no code at all, which is genuinely useful for a one-off reference dataset and genuinely unusable as a deployment mechanism.
Pick by who owns the artifact rather than by preference. SQL DDL belongs in version control and reviews cleanly, which is why it wins for anything a pipeline depends on. The Spark DataFrame path fits when the schema is a byproduct of transformation logic, and the builder API fits when the schema itself is generated from configuration or a migration mapping. Both are equally scriptable through the Databricks REST API .
REPLACE or Drop and Recreate? Databricks Has an Opinion Dropping a table and recreating it is the reflex most engineers bring from other platforms. On Databricks it quietly destroys things you probably wanted to keep.
CREATE OR REPLACE TABLE preserves the table history, granted privileges, row filters, and column masks. The syntax reference is unambiguous about the recommendation: Databricks strongly recommends using REPLACE instead of dropping and re-creating tables.
-- Keeps history, grants, row filters, and column masks
CREATE OR REPLACE TABLE main.sales.orders (
order_id BIGINT NOT NULL,
customer_id BIGINT NOT NULL,
order_ts TIMESTAMP,
order_total DECIMAL(18,2),
region STRING
);Two constraints go with it. The clause is supported only for Delta and Apache Iceberg tables, and it cannot be combined with IF NOT EXISTS, so CREATE OR REPLACE TABLE IF NOT EXISTS is rejected outright.
This also matters for idempotent deployments. IF NOT EXISTS makes a rerun succeed, but it succeeds by doing nothing, leaving an outdated schema in place while the release log says green. Comparing expected DDL against SHOW CREATE TABLE is what actually proves a deployment landed, which is why table DDL belongs in the same release path as Databricks Workflows job definitions.
Liquid Clustering Has Replaced Partitioning as the Default Most blog content on this keyword still leads with PARTITIONED BY and Z-ordering. That advice is a release cycle or three behind what Databricks now recommends for new tables.
Liquid clustering has been available since Databricks Runtime 13.3 and is generally available for Delta tables from Runtime 15.4 LTS onward. It adapts to query patterns instead of freezing a directory structure into the storage layout, which is exactly the failure mode behind high-cardinality partition sprawl. The official clustering guide now recommends it for new tables outright, and it pairs well with Photon on read-heavy workloads.
-- Pick your own keys
CREATE TABLE main.sales.orders (order_id BIGINT, region STRING, order_ts TIMESTAMP)
CLUSTER BY (region, order_ts);
-- Or let Databricks choose and re-choose them
CREATE TABLE main.sales.orders_auto (order_id BIGINT, region STRING)
CLUSTER BY AUTO;CLUSTER BY AUTO is the newer option and carries real prerequisites. It applies to Unity Catalog managed tables only and requires predictive optimization to be enabled, which is another place the managed-versus-external decision comes back around.
One hard rule catches people mid-migration. The two clauses are mutually exclusive, and asking for both raises SPECIFY_CLUSTER_BY_WITH_PARTITIONED_BY_IS_NOT_ALLOWED. Partitioning still has a place for genuinely low-cardinality, stable keys on very large tables, and liquid clustering is the better default for everything else.
Talk to Kanerika
Rethinking Your Databricks Table Layout?
Partitioning choices made years ago are usually the reason a Databricks estate reads slowly and costs more than it should. A short working session maps which tables are worth re-laying out first.
Book a Working Session → Which Table Properties Actually Matter at CREATE Time TBLPROPERTIES gets treated as decoration. Several Delta properties are much cheaper to set at creation than to retrofit onto a table with history and downstream readers.
CREATE TABLE main.sales.orders (order_id BIGINT, order_total DECIMAL(18,2))
TBLPROPERTIES (
'delta.enableChangeDataFeed' = 'true',
'delta.columnMapping.mode' = 'name',
'delta.deletedFileRetentionDuration' = 'interval 30 days',
'data_owner' = 'sales-platform',
'data_classification' = 'internal'
);Change data feed is the clearest example. Enabling it later works, but change records only exist from the moment it was switched on, so a downstream consumer built afterwards cannot reconstruct what it missed.
Column mapping mode is the other one worth deciding early. It is what allows column renames and spaces in column names, and turning it on upgrades the table’s protocol version, which affects which readers can still open it.
Retention properties deserve a deliberate number rather than the default. Shortening deleted-file retention saves storage and shortens the time-travel window teams often assume is longer than it is. Custom properties like owner and classification cost nothing and make catalog search, lineage review , and audits meaningfully easier later. They also give system tables something useful to group cost and access reporting by.
Governance Belongs in the CREATE Statement, Not the Backlog Row filters and column masks can be declared in the same statement that creates the table. Both require Databricks Runtime 12.2 LTS or above and are Unity Catalog only, and both survive a REPLACE. Declaring them here is the cheapest place to apply data access governance , because retrofitting the same controls onto a live table means coordinating with everyone already querying it.
CREATE FUNCTION main.sales.mask_email(email STRING)
RETURN CASE WHEN is_account_group_member('sales_pii') THEN email ELSE '***' END;
CREATE TABLE main.sales.customers (
customer_id BIGINT,
email STRING MASK main.sales.mask_email,
region STRING
)
WITH ROW FILTER main.sales.region_filter ON (region);Grants are the other half, and the official beginner tutorial puts them in the create workflow for a reason, which is also how Databricks security reviews expect to find them. A table nobody can read is not finished, and a table everyone can read is a finding waiting to happen.
GRANT SELECT ON TABLE main.sales.orders TO `analysts`;
ALTER TABLE main.sales.orders OWNER TO `sales-platform-owners`;Assign ownership to a group rather than a person. Individual owners leave teams, and an orphaned table with no one holding the owner privilege becomes an admin ticket at exactly the wrong moment. This is standard practice in mature data governance programs and it costs one extra line of DDL.
Listen on Spotify
What Skills Should Enterprises Look for in Databricks Developers?
Beyond Delta: Managed Iceberg and Federated Tables Two newer forms get almost no coverage in the blog tier and both solve real problems.
Managed Iceberg tables let engines outside Databricks read the table through open Iceberg APIs, in the same spirit as Delta Sharing but at the table-format level. They come with sharper constraints than Delta: PARTITIONED BY is unsupported, LOCATION is unsupported, and they must be created in Unity Catalog rather than hive_metastore.
CREATE TABLE main.sales.orders_iceberg (
order_id BIGINT,
region STRING
) USING ICEBERG
CLUSTER BY (region);Federated tables go further and skip the copy entirely. USING accepts a JDBC source name, letting a Databricks table read a system that still lives somewhere else. The current source list covers POSTGRESQL, SQLSERVER, MYSQL, BIGQUERY, NETSUITE, ORACLE, REDSHIFT, SNOWFLAKE, SQLDW, SYNAPSE, SALESFORCE, SALESFORCE_DATA_CLOUD, TERADATA, WORKDAY_RAAS, and MONGODB.
CREATE TABLE main.ops.erp_orders
USING POSTGRESQL
OPTIONS (
host 'erp-db.internal', port '5432', database 'erp', dbtable 'public.orders',
user secret('erp_scope','pg_user'),
password secret('erp_scope','pg_password')
);Note the secret() function rather than literal credentials. The secret function reference calls this out explicitly, and it is the difference between a connection string in a notebook and a connection string in an audit log. Teams evaluating whether to federate or migrate outright usually end up comparing Informatica against Databricks on total pipeline ownership rather than on query speed. For anything beyond a single table, Lakehouse Federation is the fuller pattern.
Why Your CREATE TABLE Failed: Real Databricks Error Conditions Databricks raises named error conditions with SQLSTATE codes, and the name is far more diagnostic than the stack trace under it. Reading the condition name first turns most of these into two-minute fixes.
Table 4: Common CREATE TABLE error conditions and what actually causes them
Error condition Real cause Fix INVALID_SCHEMA_OR_RELATION_NAMEHyphens, spaces, or non-ASCII characters in a hive_metastore name Use letters, digits, and underscores, or move to Unity Catalog DELTA_CREATE_TABLE_WITH_NON_EMPTY_LOCATIONThe path holds files that are not a Delta table Point at an empty path, or register the existing format explicitly DELTA_CREATE_TABLE_SCHEME_MISMATCHDeclared schema does not match the Delta data already at that path Drop the column list and let the table inherit, or match it exactly LOCATION_OVERLAPAn external path sits inside managed-table storage Choose a path outside the managed storage root SPECIFY_CLUSTER_BY_WITH_PARTITIONED_BY_IS_NOT_ALLOWEDBoth layout clauses in one definition Keep CLUSTER BY and delete PARTITIONED BY TEMP_TABLE_REPLACE_PERMANENT_NAME_CONFLICTA session temp table shadows the permanent table you meant to replace Qualify the name fully, or drop the temp table first INSUFFICIENT_PERMISSIONS_EXT_LOCNo privileges on the external location or storage credential Grant on the external location, not just the schema
One root cause sits underneath several of these and is worth stating on its own. For Delta tables, the table inherits its configuration from the LOCATION when data already exists there, so any TBLPROPERTIES, column list, or PARTITIONED BY you supply must match the existing data exactly.
That single rule explains the schema mismatch, partitioning mismatch, and property mismatch errors as one family rather than three unrelated bugs. The full catalog lives in the Databricks error conditions reference , and it is worth searching by condition name before opening a broader troubleshooting hunt.
Validate the Table Before a Pipeline Writes to It A successful CREATE TABLE proves the statement parsed. It does not prove the object matches what the pipeline expects, which is a different and more useful question.
DESCRIBE TABLE EXTENDED main.sales.orders;
DESCRIBE DETAIL main.sales.orders;
SHOW CREATE TABLE main.sales.orders;
SHOW GRANTS ON TABLE main.sales.orders;Check four things against the intended definition: column names and types, nullability, the provider and location, and the current owner and grants. DESCRIBE DETAIL is the fastest way to confirm whether you actually got a managed table, because it reports the resolved storage location. Run these checks from a notebook or a Databricks SQL warehouse , where a serverless warehouse is usually the quicker option because it starts in seconds rather than minutes.
For CTAS output, add source-to-target row counts and a null profile on the columns downstream logic depends on. Type inference errors surface as nulls and precision loss long before they surface as an exception, which is exactly why they reach production. Keeping the DDL in version control and running these checks in CI turns table creation into a reviewable change rather than a notebook cell someone ran once, the same discipline that keeps declarative pipelines reproducible.
How Kanerika Standardizes Databricks Table Design at Scale One team writing careful DDL is a habit. Two hundred tables arriving from a legacy platform is an engineering problem, and it is where table-creation decisions stop being individually reversible.
Kanerika, a Databricks Consulting Partner, ran exactly that on a healthcare provider’s migration from Informatica to Databricks. The work involved reconciling source and target schemas, mapping legacy types to Databricks types deliberately rather than by inference, and rebuilding the estate on governed Unity Catalog structures, the pattern covered in more depth in this Informatica to Databricks migration walkthrough. Published results were 71% higher reporting accuracy, a 38% reduction in data-handling costs, and 64% faster decision-making.
The reusable part is not the SQL. It is the standard applied before any of it ran: managed by default, explicit schemas on anything with downstream consumers, DDL in source control, grants assigned to groups, and validation gates that compare the created object against the intended contract.
That standard is what makes an estate survive its next migration, and it is the reason teams bring in Databricks specialists or hire Databricks developers for the first hundred tables rather than the last ten. Teams running mixed platforms across Databricks and Snowflake face the same question twice with different grammar, which is why the Snowflake CREATE TABLE decisions rhyme with these ones. Kanerika’s data engineering and Informatica to Databricks migration practices exist to make that standard hold across the whole estate rather than one well-run team.
Case Study
71% Higher Reporting Accuracy With Informatica to Databricks Migration
A leading healthcare provider moved off Informatica onto governed Databricks structures, with reconciled schemas and deliberate type mapping, reaching 71% higher reporting accuracy, 38% lower data-handling costs, and 64% faster decision-making.
Read the Case Study → Frequently Asked Questions
How do I create a table in Databricks? Run CREATE TABLE with a three-part Unity Catalog name and a column list, for example CREATE TABLE main.sales.orders (order_id BIGINT, order_total DECIMAL(18,2));. With no USING clause, Databricks creates a managed Delta table, which is the right default for most analytical workloads. You need USE CATALOG, USE SCHEMA, and CREATE TABLE privileges on the target schema before the statement will run.
What is the difference between a managed table and an external table in Databricks? A managed table lets Unity Catalog own the storage location and its lifecycle, while an external table points at a cloud path your team owns through a LOCATION clause. Dropping a managed table makes it recoverable with UNDROP for a default seven days before the files are removed. Dropping an external table removes only the metadata and leaves every file in place. Managed tables also get predictive optimization and automatic liquid clustering, which external tables do not.
Is every table in Databricks a Delta table by default? If you omit the USING clause, the default table format is Delta. You can create other formats explicitly, including managed Apache Iceberg tables with USING ICEBERG, Parquet, CSV, JSON, and federated JDBC sources. One subtlety catches teams registering raw files: for any format other than Delta or Iceberg, leaving out both LOCATION and AS query creates a managed table with no data in it.
Should I use PARTITIONED BY or liquid clustering when creating a Databricks table? Liquid clustering with CLUSTER BY is the better default for new tables. It has been available since Databricks Runtime 13.3 and is generally available for Delta tables from Runtime 15.4 LTS, and it adapts to query patterns instead of freezing a directory layout. The two clauses are mutually exclusive, so asking for both raises SPECIFY_CLUSTER_BY_WITH_PARTITIONED_BY_IS_NOT_ALLOWED. Keep PARTITIONED BY only for genuinely low-cardinality, stable keys on very large tables.
What happens to grants, row filters, and column masks when I run CREATE OR REPLACE TABLE? They are preserved. Databricks documents that REPLACE retains table history, granted privileges, row filters, and column masks, which is exactly why it strongly recommends REPLACE over dropping and recreating a table. The clause works only for Delta and Apache Iceberg tables, and it cannot be combined with IF NOT EXISTS, so CREATE OR REPLACE TABLE IF NOT EXISTS is rejected.
Why does my Databricks CREATE TABLE fail with a location is not empty error? The condition is DELTA_CREATE_TABLE_WITH_NON_EMPTY_LOCATION, and it means the path you pointed at already holds files that are not a Delta table. A related family of errors appears when the path does hold Delta data, because a Delta table inherits its configuration from the LOCATION, so any TBLPROPERTIES, column list, or PARTITIONED BY clause you supply must match the existing data exactly. Either point at an empty path or drop the explicit definition and let the table inherit it.
What is the difference between a deep clone and a shallow clone in Databricks? A deep clone copies both the data files and the metadata, producing a fully independent table that keeps partitioning, clustering, and other properties intact. A shallow clone copies metadata only and keeps pointing at the source table’s files, which makes it instant and free but tied to the source. Use deep clone for backups, archives, and environment promotion, and shallow clone for short-lived test tables you will discard.
Can I create a temporary table in Databricks? Yes. Session-local temporary tables are available in Databricks Runtime 18.1 and above and are created with CREATE TEMP TABLE using an unqualified name, with no catalog or schema prefix. They deliberately refuse most clauses: USING, LOCATION, PARTITIONED BY, CLUSTER BY, generated columns, row filters, and column masks are all unsupported. If a temp table shares a name with a permanent one, a replace attempt raises TEMP_TABLE_REPLACE_PERMANENT_NAME_CONFLICT.