mirror of
https://github.com/lancedb/lancedb.git
synced 2026-10-27 05:56:14 +00:00
docs: flip ownership of View/SQL-client/FTS-SQL/AuthZ/AuthN to OSS, restructure SQL Reference
OSS docs now own the full usage content for features that only run against an Enterprise deployment, since the client interface itself lives here; Enterprise docs keep only the parts specific to its own behavior. Sophon's overlay for these five pages is dropped since the OSS versions are now the complete reference. SQL Reference is restructured to match an object-type SQL manual (DDL by object, then DML, then DQL, then Expressions) instead of the old flat, loosely-ordered page list, absorbing the SQL client-connection guide and FTS-via-SQL examples into it.
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
---
|
||||
title: "Function"
|
||||
sidebarTitle: "Function"
|
||||
description: "CREATE FUNCTION, SHOW FUNCTIONS, and DROP FUNCTION."
|
||||
icon: function
|
||||
keywords: ["create function", "drop function", "show functions", "sql", "udf"]
|
||||
---
|
||||
|
||||
<Badge color="red">Enterprise</Badge> [SQL runs on a deployment.](/sql)
|
||||
|
||||
## CREATE FUNCTION {#create}
|
||||
|
||||
```sql
|
||||
CREATE FUNCTION f(x BIGINT) RETURNS BIGINT
|
||||
LANGUAGE python
|
||||
AS 'def f(x): return x * 2'
|
||||
WITH (pip = 'numpy==1.26.4', python_version = '3.11')
|
||||
```
|
||||
|
||||
The body is Python source. Its dependencies are declared with it and are part
|
||||
of the **immutable function version** -- changing one produces a new version
|
||||
rather than altering the registered one, so a column filled by an earlier
|
||||
version is unaffected.
|
||||
|
||||
| Option | |
|
||||
| --- | --- |
|
||||
| `pip` | pip requirements for the worker environment |
|
||||
| `conda` | conda packages instead of pip |
|
||||
| `conda_channels` | channels in priority order; requires `conda` |
|
||||
| `python_version` | worker Python version, defaulting to yours |
|
||||
| `gpu` | `'true'` when every execution needs a GPU |
|
||||
|
||||
**Errors and limits**
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| `LANGUAGE` other than `python` | refused |
|
||||
| `pip` and `conda` together | refused -- pick one |
|
||||
| `conda_channels` without `conda` | refused |
|
||||
| `gpu` set to anything but `'true'` | refused |
|
||||
| An empty body | refused |
|
||||
| Any other option | refused, and the message lists what is supported |
|
||||
|
||||
<Note>
|
||||
**Enterprise job type:** `create_function`. Registration returns a job because
|
||||
the function is baked into an image before the version becomes usable.
|
||||
</Note>
|
||||
|
||||
## SHOW FUNCTIONS {#show}
|
||||
|
||||
```sql
|
||||
SHOW FUNCTIONS
|
||||
```
|
||||
|
||||
Lists registered functions and their versions. Since a version is immutable
|
||||
and a column pins the version that fills it, this is how you find which
|
||||
versions are still in use before dropping one.
|
||||
|
||||
## DROP FUNCTION {#drop}
|
||||
|
||||
```sql
|
||||
DROP FUNCTION embed WITH (version = '1')
|
||||
DROP FUNCTION IF EXISTS embed WITH (version = '1')
|
||||
DROP FUNCTION embed WITH (version = '1', cascade = 'true')
|
||||
```
|
||||
|
||||
`version` is required -- a function is a set of immutable versions, and
|
||||
dropping is always of one specific version, never "the function" as a whole.
|
||||
|
||||
<Warning>
|
||||
Without `cascade = 'true'`, dropping a version that a column still pins fails
|
||||
rather than breaking that column silently. Passing it drops the version and
|
||||
lets columns pinned to it stop refreshing -- they keep their last-filled
|
||||
values, per [Guarantees](/basics/guarantees#jobs).
|
||||
</Warning>
|
||||
|
||||
## What to read next {#next}
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Function" icon="function" href="/management/function">
|
||||
Registering one from the SDK, and diagnosing environment mismatches.
|
||||
</Card>
|
||||
<Card title="Computed columns" icon="table-columns" href="/feature-engineering/add-computed-column">
|
||||
Filling a column with a function instead of an expression.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
title: "Index"
|
||||
sidebarTitle: "Index"
|
||||
description: "CREATE INDEX and DROP INDEX — one column, server-chosen name."
|
||||
icon: bolt
|
||||
keywords: ["create index", "drop index", "sql"]
|
||||
---
|
||||
|
||||
<Badge color="red">Enterprise</Badge> [SQL runs on a deployment.](/sql)
|
||||
|
||||
## CREATE INDEX {#create}
|
||||
|
||||
```sql
|
||||
CREATE INDEX ON documents (title)
|
||||
```
|
||||
|
||||
<Note>
|
||||
SQL `CREATE INDEX` covers **one column** and takes **no user-chosen name** --
|
||||
the server names it. For a multi-column or explicitly-named index, or to
|
||||
choose the algorithm, use the SDK's
|
||||
[`create_index`](/indexing#choosing-an-index).
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
**Enterprise job type:** `create_ivf_pq`, `create_btree`, `create_fts`, and one
|
||||
more per algorithm -- the type names which algorithm is building, not a
|
||||
different feature. See [Build & Repair](/indexing/reindexing).
|
||||
</Note>
|
||||
|
||||
## DROP INDEX {#drop}
|
||||
|
||||
```sql
|
||||
DROP INDEX documents.title_idx
|
||||
```
|
||||
|
||||
Takes the qualified `table.index` name. Find it with the SDK's
|
||||
[`list_indices`](/indexing#choosing-an-index) if you created the index without
|
||||
naming it yourself.
|
||||
|
||||
## What to read next {#next}
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Indexing" icon="bolt" href="/indexing">
|
||||
Choosing an index type from the SDK.
|
||||
</Card>
|
||||
<Card title="Build & Repair" icon="refresh" href="/indexing/reindexing">
|
||||
Keeping an index current as data arrives.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: "Job"
|
||||
sidebarTitle: "Job"
|
||||
description: "SHOW JOBS, SHOW ERRORS, and controlling a running job with PAUSE, RESUME and CANCEL."
|
||||
icon: hourglass-half
|
||||
keywords: ["show jobs", "show errors", "pause job", "resume job", "cancel job", "sql"]
|
||||
---
|
||||
|
||||
<Badge color="red">Enterprise</Badge> [SQL runs on a deployment.](/sql)
|
||||
|
||||
A [job](/basics/jobs) is not a catalog object -- it has no schema and is not
|
||||
namespaced -- but it has its own SQL statements, grouped here the same way the
|
||||
catalog objects are.
|
||||
|
||||
## SHOW JOBS {#show}
|
||||
|
||||
```sql
|
||||
SHOW JOBS
|
||||
```
|
||||
|
||||
Every job the server knows about -- id, type, state, creation time. The SQL
|
||||
counterpart of `list_jobs`.
|
||||
|
||||
## SHOW ERRORS {#errors}
|
||||
|
||||
```sql
|
||||
SHOW ERRORS ON <table> [FOR JOB '<job-id>'] [LIMIT <n>]
|
||||
```
|
||||
|
||||
```sql
|
||||
SHOW ERRORS ON documents
|
||||
SHOW ERRORS ON documents FOR JOB 'job-abc' LIMIT 100
|
||||
```
|
||||
|
||||
Why rows failed. Reach for this when a [refresh](/sql/dml/refresh) reports
|
||||
fewer filled rows than you expected.
|
||||
|
||||
**Errors and limits**
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| `LIMIT` | must be between 1 and 100,000 |
|
||||
| Failed jobs scanned without `FOR JOB` | 32 most recent |
|
||||
| Tables the server does not open directly | not supported |
|
||||
|
||||
Without `FOR JOB` this surveys recent failures and stops at 32 jobs. When the
|
||||
listing stops at your `LIMIT`, the message says so -- narrow with `FOR JOB`
|
||||
rather than raising the limit blindly.
|
||||
|
||||
## PAUSE JOB {#pause}
|
||||
|
||||
```sql
|
||||
PAUSE JOB 'j-ci-abc-def'
|
||||
```
|
||||
|
||||
## RESUME JOB {#resume}
|
||||
|
||||
```sql
|
||||
RESUME JOB 'j-ci-abc-def'
|
||||
```
|
||||
|
||||
## CANCEL JOB {#cancel}
|
||||
|
||||
```sql
|
||||
CANCEL JOB 'j-ci-abc-def'
|
||||
```
|
||||
|
||||
The job id is always a quoted string literal. All three take exactly one and
|
||||
nothing after it -- a second token on the line is a syntax error rather than
|
||||
being ignored.
|
||||
|
||||
<Note>
|
||||
Cancellation is a request, matching the SDK's
|
||||
[`cancel()`](/basics/jobs#managing): it does not guarantee the job stops before
|
||||
doing more work, and asking twice or cancelling a finished job does nothing.
|
||||
`CANCEL JOB` itself can be unavailable on a deployment with no job registry
|
||||
configured, which is a deployment condition rather than something you can work
|
||||
around from SQL.
|
||||
</Note>
|
||||
|
||||
## What to read next {#next}
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Query and job" icon="hourglass-half" href="/basics/jobs">
|
||||
The handle these statements are the SQL view of.
|
||||
</Card>
|
||||
<Card title="Background jobs" icon="gears" href="/maintenance/background-jobs">
|
||||
Job types you did not start yourself.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
title: "Materialized View"
|
||||
sidebarTitle: "Materialized View"
|
||||
description: "SHOW MATERIALIZED VIEWS — creation and refresh are SDK and REFRESH statements, not CREATE."
|
||||
icon: table
|
||||
keywords: ["materialized view", "show materialized views", "sql"]
|
||||
---
|
||||
|
||||
<Badge color="red">Enterprise</Badge> [SQL runs on a deployment.](/sql)
|
||||
|
||||
A materialized view stores a query's result as rows, kept current by a refresh
|
||||
-- the counterpart to a [view](/sql/ddl/view), which stores only the query.
|
||||
|
||||
<Note>
|
||||
There is no `CREATE MATERIALIZED VIEW` statement. Creation is
|
||||
[`create_materialized_view`](/management/materialized-view#create) in the SDK,
|
||||
since it needs SDK-level source-table validation (stable row ids) that a bare
|
||||
SQL statement has nowhere to check. Once created, it is entirely a SQL object:
|
||||
queried like a table, refreshed with SQL, listed with SQL.
|
||||
</Note>
|
||||
|
||||
## SHOW MATERIALIZED VIEWS {#show}
|
||||
|
||||
```sql
|
||||
SHOW MATERIALIZED VIEWS
|
||||
```
|
||||
|
||||
<Note>
|
||||
Cheaper than the SDK equivalent. `list_materialized_views` finds views by
|
||||
reading every table's schema, costing one open per table; this asks the server.
|
||||
</Note>
|
||||
|
||||
## Refreshing one {#refresh}
|
||||
|
||||
```sql
|
||||
REFRESH MATERIALIZED VIEW chunks
|
||||
```
|
||||
|
||||
See [REFRESH](/sql/dml/refresh#refresh-materialized-view) for the full syntax,
|
||||
including `full = true` and what `CASCADE` does not yet do.
|
||||
|
||||
## Dropping one {#drop}
|
||||
|
||||
A materialized view **is** a table, so it is dropped with
|
||||
[`DROP TABLE`](/sql/ddl/table#drop) -- which is also why dropping one removes
|
||||
stored rows, unlike dropping a [view](/sql/ddl/view#drop).
|
||||
|
||||
<Note>
|
||||
**Enterprise job type:** `mat_view_refresh` for the refresh; `drop_table` for
|
||||
dropping it, same as any table.
|
||||
</Note>
|
||||
|
||||
## What to read next {#next}
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Materialized View" icon="table" href="/management/materialized-view">
|
||||
Creating one from the SDK, and the stable-row-ids requirement.
|
||||
</Card>
|
||||
<Card title="Refresh a materialized view" icon="arrows-rotate" href="/feature-engineering/materialized-views">
|
||||
Incremental refreshes, and what they cost.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: "Namespace"
|
||||
sidebarTitle: "Namespace"
|
||||
description: "CREATE SCHEMA and DROP SCHEMA — the SQL spelling of namespace DDL."
|
||||
icon: folder-tree
|
||||
keywords: ["namespace", "schema", "create schema", "drop schema", "sql"]
|
||||
---
|
||||
|
||||
<Badge color="red">Enterprise</Badge> [SQL runs on a deployment.](/sql)
|
||||
|
||||
A [namespace](/management/namespace) is addressed in SQL as a `SCHEMA` -- the
|
||||
standard's name for the same concept.
|
||||
|
||||
## CREATE SCHEMA {#create}
|
||||
|
||||
```sql
|
||||
CREATE SCHEMA public
|
||||
CREATE SCHEMA db1.ns1.ns2
|
||||
CREATE SCHEMA IF NOT EXISTS `ns1$ns2`
|
||||
```
|
||||
|
||||
A dotted path creates the whole chain: `db1.ns1.ns2` creates `ns2` inside
|
||||
`ns1` inside `db1`, provided the parents already exist. A name containing the
|
||||
namespace path delimiter itself is backtick-quoted, as in `` `ns1$ns2` `` above.
|
||||
|
||||
`IF NOT EXISTS` makes the statement a no-op rather than an error when the
|
||||
namespace is already there.
|
||||
|
||||
## DROP SCHEMA {#drop}
|
||||
|
||||
```sql
|
||||
DROP SCHEMA db1.public
|
||||
DROP SCHEMA IF EXISTS `a$b`
|
||||
DROP SCHEMA `a$b` RESTRICT
|
||||
```
|
||||
|
||||
<Warning>
|
||||
`CASCADE` is rejected: **"DROP SCHEMA CASCADE is not supported; drop the
|
||||
objects inside first."** A namespace's tables, views and functions must be
|
||||
dropped explicitly before the namespace itself can go. `RESTRICT` -- the
|
||||
default -- states that requirement rather than changing it.
|
||||
</Warning>
|
||||
|
||||
## What to read next {#next}
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Namespace" icon="folder-tree" href="/management/namespace">
|
||||
The SDK equivalent, and how a namespace fits the catalog hierarchy.
|
||||
</Card>
|
||||
<Card title="Table" icon="table" href="/sql/ddl/table">
|
||||
Creating tables inside a namespace.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,178 @@
|
||||
---
|
||||
title: "Table"
|
||||
sidebarTitle: "Table"
|
||||
description: "CREATE, DESCRIBE, ALTER, CLONE and DROP TABLE."
|
||||
icon: table
|
||||
keywords: ["create table", "alter table", "drop table", "describe", "clone", "ddl"]
|
||||
---
|
||||
|
||||
<Badge color="red">Enterprise</Badge> [SQL runs on a deployment.](/sql)
|
||||
|
||||
## CREATE TABLE {#create}
|
||||
|
||||
```sql
|
||||
CREATE TABLE documents (id BIGINT, title VARCHAR, created_at TIMESTAMP)
|
||||
CREATE TABLE recent AS SELECT * FROM documents WHERE created_at > now() - INTERVAL '7 days'
|
||||
```
|
||||
|
||||
Column types are Arrow types under SQL names -- see [Data types](/sql/data-types).
|
||||
A table inside a [namespace](/sql/ddl/namespace) is written as a dotted path:
|
||||
`prod.events.clicks`.
|
||||
|
||||
## DESCRIBE {#describe}
|
||||
|
||||
```sql
|
||||
DESCRIBE documents
|
||||
```
|
||||
|
||||
The table's columns and types, without a plan -- the SQL counterpart of
|
||||
`table.schema`.
|
||||
|
||||
## ALTER TABLE {#alter}
|
||||
|
||||
`ALTER TABLE ... ADD COLUMN` covers three different things, distinguished by
|
||||
what follows the column name.
|
||||
|
||||
### A plain column {#plain-column}
|
||||
|
||||
```sql
|
||||
ALTER TABLE t ADD COLUMN c INT
|
||||
```
|
||||
|
||||
Added empty and nullable. Nothing is computed.
|
||||
|
||||
### A computed column {#computed-column}
|
||||
|
||||
```sql
|
||||
ALTER TABLE t ADD COLUMN doubled AS value * 2
|
||||
```
|
||||
|
||||
`AS <expression>` declares a [computed column](/feature-engineering/add-computed-column).
|
||||
The column is committed empty and the expression is stored, not evaluated --
|
||||
declaring one on a billion-row table costs what declaring one on an empty table
|
||||
costs. [`REFRESH COLUMN`](/sql/dml/refresh) fills it.
|
||||
|
||||
### A function column {#function-column}
|
||||
|
||||
```sql
|
||||
ALTER TABLE t ADD COLUMN embedded AS embed(name) WITH (version = 'fv_1')
|
||||
```
|
||||
|
||||
When the expression calls a [registered function](/sql/ddl/function), the
|
||||
column is filled by running that function on workers. `version` pins which
|
||||
immutable function version fills it, so a later registration does not silently
|
||||
change what the column means.
|
||||
|
||||
Several modifiers narrow what gets computed:
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| `FILTER (WHERE pred)` | only rows matching `pred` are computed |
|
||||
| `IGNORE NULLS` | rows with null inputs are skipped |
|
||||
| `OVER (PARTITION BY col)` | the function sees rows grouped by `col` |
|
||||
|
||||
A function returning several values fills several columns at once:
|
||||
|
||||
```sql
|
||||
ALTER TABLE t ADD COLUMN (label, score) AS classify(text) WITH (version = 'fv_1')
|
||||
```
|
||||
|
||||
```sql
|
||||
ALTER TABLE t ADD COLUMN c AS f(x) FILTER (WHERE keep) WITH (version = 'fv_1')
|
||||
ALTER TABLE t ADD COLUMN c AS f(x) WITH (num_workers = '2')
|
||||
```
|
||||
|
||||
<Note>
|
||||
`WITH` on a plain computed column accepts only `version`. Resource options such
|
||||
as `num_workers` apply to function columns, where there are workers to size.
|
||||
</Note>
|
||||
|
||||
### Table properties {#properties}
|
||||
|
||||
```sql
|
||||
ALTER TABLE t SET UNENFORCED PRIMARY KEY (id)
|
||||
```
|
||||
|
||||
Records which column identifies a row. **Unenforced** is not a hedge in the
|
||||
naming: uniqueness is not checked on write, and declaring it does not make
|
||||
duplicates impossible. It tells the planner what to assume.
|
||||
|
||||
```sql
|
||||
ALTER TABLE t SET WAL
|
||||
ALTER TABLE t SET WAL WITH (sharding = 'bucket', buckets = 4)
|
||||
ALTER TABLE t SET WAL WITH (maintained_indexes = '')
|
||||
ALTER TABLE t UNSET WAL
|
||||
```
|
||||
|
||||
A write-ahead log makes small frequent writes cheap by batching them out of the
|
||||
commit path. `sharding` and `buckets` spread the log so concurrent writers do
|
||||
not contend on one place; `maintained_indexes` chooses which indexes are kept
|
||||
current against WAL rows. See
|
||||
[Background jobs](/maintenance/background-jobs#wal) for how the log gets
|
||||
folded back into the table.
|
||||
|
||||
<Warning>
|
||||
[`TABLESAMPLE`](/sql/dql/sampling) is refused on a WAL-backed table, because
|
||||
rows a sample would draw from are not all in the fragments yet.
|
||||
</Warning>
|
||||
|
||||
**Errors and limits**
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| `ALTER TABLE ... DROP COLUMN` | not supported |
|
||||
|
||||
Dropping, renaming, or retyping a column is an SDK operation --
|
||||
[`drop_columns`](/management/table#schema) and
|
||||
[`alter_columns`](/management/table#schema) -- not a SQL statement.
|
||||
|
||||
## CLONE {#clone}
|
||||
|
||||
```sql
|
||||
CREATE TABLE docs_snapshot CLONE documents
|
||||
CREATE TABLE docs_at_v42 CLONE documents AT 42
|
||||
CREATE TABLE docs_at_release CLONE documents AT TAG 'release-1'
|
||||
CREATE TABLE docs_yesterday CLONE documents AT TIMESTAMP '2026-09-01T00:00:00Z'
|
||||
```
|
||||
|
||||
A **shallow clone**: the new table shares the source's data files rather than
|
||||
copying them, so it costs one metadata commit regardless of the source's size.
|
||||
|
||||
`AT` pins the point in the source's history to clone. A bare integer is a
|
||||
version and a bare quoted string is a timestamp; `VERSION`, `TAG` and
|
||||
`TIMESTAMP` say so explicitly, and a tag always needs its keyword -- a bare
|
||||
quoted string cannot be both a tag name and a timestamp.
|
||||
|
||||
<Warning>
|
||||
The clone depends on the source's files continuing to exist. If the source is
|
||||
[compacted](/maintenance/cleanup) past the retention window, the version the
|
||||
clone points at can be pruned. The SDK's
|
||||
[`clone_table`](/management/table#rename-clone) also offers a deep clone for
|
||||
when the copy has to outlive the source's history.
|
||||
</Warning>
|
||||
|
||||
## DROP TABLE {#drop}
|
||||
|
||||
```sql
|
||||
DROP TABLE documents
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Removes the table and every version of it. There is no undrop.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
**Enterprise job type:** `drop_table`. See
|
||||
[Background jobs](/maintenance/background-jobs#teardown).
|
||||
</Note>
|
||||
|
||||
## What to read next {#next}
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Table" icon="table" href="/management/table">
|
||||
The SDK equivalent, and what a table carries.
|
||||
</Card>
|
||||
<Card title="Schema evolution" icon="boxes-stacked" href="/management/table#schema">
|
||||
Renaming, retyping and dropping columns from the SDK.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: "View"
|
||||
sidebarTitle: "View"
|
||||
description: "CREATE VIEW and DROP VIEW — a saved query, evaluated when read."
|
||||
icon: eye
|
||||
keywords: ["create view", "drop view", "sql", "catalog"]
|
||||
---
|
||||
|
||||
<Badge color="red">Enterprise</Badge> [SQL runs on a deployment.](/sql)
|
||||
|
||||
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.
|
||||
|
||||
There is no SDK method for a view, because the thing it stores *is* a SQL
|
||||
statement.
|
||||
|
||||
## 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 the view's schema -- column name, data type, nullability
|
||||
-- resolved from the query at creation time. 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}
|
||||
|
||||
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>
|
||||
Reference in New Issue
Block a user