Files
lancedb/docs/web/sql/ddl/view.mdx
T
Jack Ye cbc24fa84f fix: decode native SQL view metadata (#4785)
View APIs now read the native `name`, `query`, and `schema` columns
returned by `CREATE VIEW` and `DESCRIBE VIEW`. The schema JSON carries
the defining database and namespace; the requested namespace identifies
where the view lives. The unreleased JSON-envelope response is removed
without a compatibility fallback.

```python
view = db.create_view("adults", "SELECT name FROM people WHERE age >= 18")
view = db.describe_view("adults")
```

```sql
CREATE VIEW "adults" AS SELECT name FROM people WHERE age >= 18;
DESCRIBE VIEW "adults";
```

Both Python calls execute SQL through the query-backed job adapter and
wait on the resulting query. A job handle uses that query's `id` and
type `query`; reading metadata consumes its completed result rather than
resubmitting the DDL. Creation returns the definition from the creating
execution, with no extra describe request.
2026-11-02 01:15:36 +08:00

119 lines
4.0 KiB
Plaintext

---
title: "View"
sidebarTitle: "View"
description: "Create, describe, list, and drop saved queries with SQL."
icon: eye
keywords: ["create view", "drop view", "sql", "catalog"]
availability:
embedded: unavailable
enterprise: available
---
A view stores a **query**, not rows. Reading it runs the query against current
data, so a view is never stale, and never faster than the query it wraps. It
is the counterpart to a [materialized view](/sql/ddl/materialized-view), which
stores rows and is brought up to date by a refresh; both are
[catalog objects](/basics/catalog) defined by a query, differing only in when
that query runs.
The SDK methods `create_view`, `describe_view`, `list_views`, and `drop_view`
submit SQL through the connection's Flight endpoint. `drop_view_async` returns
a job of type `query` whose single `id` is the SQL query UUID. Waiting confirms
catalog removal; physical cleanup can continue afterward.
## CREATE VIEW {#create}
```sql
CREATE VIEW "recent_matches" AS
SELECT t1.floats
FROM "documents" AS t1
INNER JOIN "categories" AS t2 ON t1.ints = t2.ints
```
The statement returns one row with UTF-8 `name`, `query`, and `schema` columns.
`query` contains the stored query, including any declared column aliases, and
`schema` contains its Arrow schema as JSON. The schema metadata keys
`lancedb::view::default_db` and `lancedb::view::default_namespace` identify the
defining database and namespace. The root namespace is `public`; nested
namespace components are separated by `$`.
`DESCRIBE VIEW "recent_matches"` returns the same metadata shape. Anything the
[dialect](/sql/functions) supports can define one: joins, predicates,
aggregates, window functions.
## Reading one {#reading}
A view is queried like a table:
```sql
SELECT * FROM "recent_matches" WHERE floats > 0.5
```
Predicates applied to the view compose with the query inside it rather than
filtering its output afterwards, so a selective filter does not pay for rows
the view would have produced and then discarded.
## DROP VIEW {#drop}
```sql
DROP VIEW "recent_matches"
```
Removes the saved query. Unlike dropping a table, no data is removed: there
was none to begin with.
## Listing {#listing}
```sql
SHOW VIEWS
SHOW VIEWS IN "analytics" WHERE name > 'previous_view' LIMIT 100
```
`SHOW VIEWS` returns ascending `name` values. The `name` cursor is scoped to
the selected namespace.
Object commands retain their small results in shared storage even when general
query-result copying is disabled, so asynchronous polling can use any query node.
Views and tables share a namespace, and both are things you can query. The
catalog distinguishes them:
| | |
| --- | --- |
| view names | the views in the database |
| table names | the tables |
| relation names | everything queryable (both) |
Use the relation listing when the question is "what can I select from," and the
separate listings when the distinction matters: before dropping, for
instance, since dropping a view removes only the saved query while dropping a
table removes data.
## Choosing between a view and a materialized view {#choosing}
| | View | Materialized view |
| --- | --- | --- |
| Stores | the query | the rows |
| Freshness | always current | as of the last refresh |
| Read cost | the full query, every read | a table scan |
| Write cost | none | a refresh |
Reach for a **view** when the query is cheap, or when reading stale rows would
be wrong. Reach for a **materialized view** when the query is expensive and the
data changes less often than it is read.
The privileges are separate too: `CREATE_VIEW` and `CREATE_MATERIALIZED_VIEW`
are distinct grants on a namespace, so the ability to create one does not imply
the other. See [Authorization](/governance/authorization).
## What to read next {#next}
<CardGroup cols={2}>
<Card title="Materialized View" icon="table" href="/sql/ddl/materialized-view">
The stored-rows counterpart.
</Card>
<Card title="Management" icon="folder-tree" href="/management">
Where views fit among the other catalog objects.
</Card>
</CardGroup>