mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
Remove duplicate tables file
This commit is contained in:
1 parent
bdda1e970e
commit
a38b0ea74f
1 file changed
-354
@@ -1,354 +0,0 @@
|
||||
---
|
||||
id: tables
|
||||
title: Tables and Data
|
||||
description: Creating and using Postgres tables.
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
|
||||
Tables are where you store your data.
|
||||
|
||||
|
||||
Tables are similar to excel spreadsheets. They contain columns and rows.
|
||||
For example, this table has 3 "columns" (`id`, `name`, `description`) and 4 "rows" of data:
|
||||
|
||||
| `id` | `name` | `description` |
|
||||
| ---- | ---- | ----------- |
|
||||
| 1 | The Phantom Menace | Two Jedi escape a hostile blockade to find allies and come across a young boy who may bring balance to the Force. |
|
||||
| 2 | Attack of the Clones | Ten years after the invasion of Naboo, the Galactic Republic is facing a Separatist movement. |
|
||||
| 3 | Revenge of the Sith | As Obi-Wan pursues a new threat, Anakin acts as a double agent between the Jedi Council and Palpatine and is lured into a sinister plan to rule the galaxy. |
|
||||
| 4 | Star Wars | Luke Skywalker joins forces with a Jedi Knight, a cocky pilot, a Wookiee and two droids to save the galaxy from the Empire's world-destroying battle station. |
|
||||
|
||||
There are a few important differences from a spreadsheet, but it's a good starting point if you're new to Relational databases.
|
||||
|
||||
## Creating Tables
|
||||
|
||||
|
||||
When creating a table, it's best practice to add columns at the same time.
|
||||
|
||||

|
||||
|
||||
You must define the "data type" of each column when it is created. You can add and remove columns at any time after creating a table.
|
||||
|
||||
Supabase provides several options for creating tables. You can use the Dashboard or create them directly using SQL.
|
||||
We provide a SQL editor within the Dashboard, or you can [connect](/docs/guides/database/connecting/connecting-to-postgres) to your database
|
||||
and run the SQL queries yourself.
|
||||
|
||||
|
||||
<Tabs
|
||||
defaultValue="UI"
|
||||
values={[
|
||||
{label: 'Dashboard', value: 'UI'},
|
||||
{label: 'SQL', value: 'SQL'},
|
||||
]}>
|
||||
<TabItem value="UI">
|
||||
|
||||
|
||||
<video width="99%" muted playsInline controls="true">
|
||||
<source src="/docs/videos/api/api-create-table-sm.mp4" type="video/mp4" muted playsInline />
|
||||
</video>
|
||||
|
||||
```sh
|
||||
1. Go to the "Table editor" section.
|
||||
2. Click "New Table".
|
||||
3. Enter the table name "todos".
|
||||
4. Click "Save".
|
||||
5. Click "New Column".
|
||||
6. Enter the column name "task" and make the type "text".
|
||||
7. Click "Save".
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="SQL">
|
||||
|
||||
```sql
|
||||
create table movies (
|
||||
id bigint generated by default as identity primary key,
|
||||
name text,
|
||||
description text
|
||||
);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
It is best practice to use lowercase and underscores when naming tables. For example: `table_name`, not `Table Name`.
|
||||
|
||||
## Columns
|
||||
|
||||
You must define the "data type" when you create a column.
|
||||
|
||||
|
||||
### Data types
|
||||
|
||||
Every column is a predefined type. PostgreSQL provides many [default types](https://www.postgresql.org/docs/current/datatype.html), and you can even design your own (or use extensions) if the default types don't fit your needs.
|
||||
|
||||
Here's list of all of the default data types provided by Postgres:
|
||||
|
||||
<details>
|
||||
<summary>Show/Hide default data types</summary>
|
||||
|
||||
| `Name` | `Aliases` | `Description` |
|
||||
| ------------------------------------------- | -------------------- | ----------------------------------------------------------------- |
|
||||
| bigint | int8 | Signed eight-byte integer. For numbers ranging from -9223372036854775808 to +9223372036854775807. |
|
||||
| bigserial | serial8 | Autoincrementing eight-byte integer. For numbers ranging from 1 to 9223372036854775807. |
|
||||
| bit | | Fixed-length bit string. |
|
||||
| bit varying | varbit | Variable-length bit string. |
|
||||
| boolean | bool | Logical Boolean (true/false). |
|
||||
| box | | Rectangular box on a plane. |
|
||||
| bytea | | Binary data (“byte array”). |
|
||||
| character | char | Fixed-length character string. |
|
||||
| character varying | varchar | Variable-length character string. |
|
||||
| cidr | | IPv4 or IPv6 network address. |
|
||||
| circle | | Circle on a plane. |
|
||||
| date | | Calendar date (year, month, day). |
|
||||
| double precision | float8 | Double precision floating-point number (8 bytes). 15 decimal digits of precision. |
|
||||
| inet | | IPv4 or IPv6 host address. |
|
||||
| integer | int, int4 | Signed four-byte integer. -2147483648 to +2147483647. |
|
||||
| interval \[ fields \] | | Time span. |
|
||||
| json | | Textual JSON data. |
|
||||
| jsonb | | Binary JSON data, decomposed. If you are doing a lot of JSON manipulation in Postgres you should consider using JSONB for efficiency. Otherwise, if you are just doing typical data storing and fetching, JSON should be fine. |
|
||||
| line | | Infinite line on a plane. |
|
||||
| lseg | | Line segment on a plane. |
|
||||
| macaddr | | MAC (Media Access Control) address. |
|
||||
| macaddr8 | | MAC (Media Access Control) address (EUI-64 format). |
|
||||
| money | | currency. |
|
||||
| numeric | decimal | Exact numeric of selectable precision. Up to 131072 digits before the decimal point; up to 16383 digits after. For storing number that require very high precision. Use the numeric type when you need more precision than float4 or float8 offer. |
|
||||
| path | | Geometric path on a plane. |
|
||||
| pg\_lsn | | PostgreSQL Log Sequence Numb. |
|
||||
| pg\_snapshot | | User-level transaction ID snapshot. |
|
||||
| point | | Geometric point on a plane. |
|
||||
| polygon | | Closed geometric path on a plane. |
|
||||
| real | float4 | Single precision floating-point number (4 byte). 6 decimal digits precision. |
|
||||
| smallint | int2 | Signed two-byte integer. For numbers ranging from -32768 to +32767 |
|
||||
| smallserial | serial2 | Autoincrementing two-byte integer. For numbers ranging from 1 to 32767. |
|
||||
| serial | serial4 | Autoincrementing four-byte integer. For numbers ranging from 1 to 2147483647 |
|
||||
| text | | Variable-length character string. This is the general purpose data type for textual content. |
|
||||
| time \[ without time zone \] | | Time of day (no time zone). |
|
||||
| time with time zone | timetz | Time of day, including time zone. |
|
||||
| timestamp \[ without time zone \] | | Date and time (no time zone). |
|
||||
| timestamp with time zone | timestamptz | Date and time, including time zone. |
|
||||
| tsquery | | Text search query. |
|
||||
| tsvector | | Text search document . |
|
||||
| txid\_snapshot | | User-level transaction ID snapshot (deprecated; see pg\_snapshot). |
|
||||
| uuid | | Universally unique identifier. |
|
||||
| xml | | XML data. |
|
||||
</details>
|
||||
|
||||
|
||||
<br />
|
||||
|
||||
You can "cast" columns from one type to another, however there can be some incompatibilities between types.
|
||||
For example, if you cast a `timestamp` to a `date`, you will lose all the time information that was previously saved.
|
||||
|
||||
### Primary Keys
|
||||
|
||||
A table can have a "primary key" - a unique identifier for every row of data. A few tips for Primary Keys:
|
||||
|
||||
|
||||
- It's recommended to create a Primary Key for every table in your database.
|
||||
- You can use any column as a primary key, as long as it is unique for every row.
|
||||
- It's common to use a `uuid` type or a numbered `identity` column as your primary key.
|
||||
|
||||
```sql
|
||||
create table movies (
|
||||
id bigint generated always as identity primary key
|
||||
);
|
||||
```
|
||||
|
||||
In the example above, we have:
|
||||
|
||||
1. created a column called `id`
|
||||
1. assigned the data type `bigint`
|
||||
1. instructed the database that this should be `generated always as identity`, which means that Postgres will automatically assign a unique number to this column.
|
||||
1. Becuase it's unique, we can also use it as our `primary key`.
|
||||
|
||||
We could also use `generated by default as identity`, which would allow us to insert our own unique values.
|
||||
|
||||
```sql
|
||||
create table movies (
|
||||
id bigint generated by default as identity primary key
|
||||
);
|
||||
```
|
||||
|
||||
## Loading data
|
||||
|
||||
There are several ways to load data in Supabase. You can load data directly into the database or using the [APIs](/docs/guides/api).
|
||||
Use the "Bulk Loading" instructions if you are loading large data sets.
|
||||
|
||||
### Basic data loading
|
||||
|
||||
<Tabs
|
||||
defaultValue="SQL"
|
||||
values={[
|
||||
{label: 'SQL', value: 'SQL'},
|
||||
{label: 'JavaScript', value: 'JS'},
|
||||
{label: 'Dart', value: 'DART'},
|
||||
]}>
|
||||
<TabItem value="SQL">
|
||||
|
||||
```sql
|
||||
insert into movies
|
||||
(name, description)
|
||||
values
|
||||
('The Empire Strikes Back', 'After the Rebels are brutally overpowered by the Empire on the ice planet Hoth, Luke Skywalker begins Jedi training with Yoda.'),
|
||||
('Return of the Jedi', 'After a daring mission to rescue Han Solo from Jabba the Hutt, the Rebels dispatch to Endor to destroy the second Death Star.');
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="JS">
|
||||
|
||||
```sql
|
||||
const { data, error } = await supabase
|
||||
.from('movies')
|
||||
.insert([{
|
||||
name: 'The Empire Strikes Back',
|
||||
description: 'After the Rebels are brutally overpowered by the Empire on the ice planet Hoth, Luke Skywalker begins Jedi training with Yoda.'
|
||||
}, {
|
||||
name: 'Return of the Jedi',
|
||||
description: 'After a daring mission to rescue Han Solo from Jabba the Hutt, the Rebels dispatch to Endor to destroy the second Death Star.'
|
||||
}])
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="DART">
|
||||
|
||||
```sql
|
||||
final res = await supabase
|
||||
.from('movies')
|
||||
.insert([{
|
||||
name: 'The Empire Strikes Back',
|
||||
description: 'After the Rebels are brutally overpowered by the Empire on the ice planet Hoth, Luke Skywalker begins Jedi training with Yoda.'
|
||||
}, {
|
||||
name: 'Return of the Jedi',
|
||||
description: 'After a daring mission to rescue Han Solo from Jabba the Hutt, the Rebels dispatch to Endor to destroy the second Death Star.'
|
||||
}]).execute();
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Bulk data loading
|
||||
|
||||
When inserting large data sets it's best to use PostgreSQL's [COPY](https://www.postgresql.org/docs/current/sql-copy.html) command.
|
||||
This loads data directly from a file into a table. There are several file formats available for copying data: text, csv, binary, JSON, etc.
|
||||
|
||||
For example, if you wanted to load a CSV file into your movies table:
|
||||
|
||||
```csv title="./movies.csv"
|
||||
"The Empire Strikes Back", "After the Rebels are brutally overpowered by the Empire on the ice planet Hoth, Luke Skywalker begins Jedi training with Yoda."
|
||||
"Return of the Jedi", "After a daring mission to rescue Han Solo from Jabba the Hutt, the Rebels dispatch to Endor to destroy the second Death Star."
|
||||
```
|
||||
|
||||
You would [connect](/docs/guides/database/connecting-to-postgres#direct-connections) to your database directly and load the file with the COPY command:
|
||||
|
||||
```bash
|
||||
psql -h DATABASE_URL -p 5432 postgres -U postgres \
|
||||
-c "COPY movies FROM './movies.csv';"
|
||||
```
|
||||
|
||||
|
||||
## Joining tables with Foreign Keys
|
||||
|
||||
Tables can be "joined" together using Foreign Keys.
|
||||
|
||||

|
||||
|
||||
This is where the "Relational" naming comes from, as data typically forms some sort of relationship.
|
||||
|
||||
In our "movies" example above, we might want to add a "category" for each movie (for example, "Action", or "Documentary").
|
||||
Let's create a new table called `categories` and "link" our `movies` table.
|
||||
|
||||
```sql
|
||||
create table categories (
|
||||
id bigint generated always as identity primary key,
|
||||
name text -- category name
|
||||
);
|
||||
|
||||
alter table movies
|
||||
add column category_id bigint references categories;
|
||||
```
|
||||
|
||||
You can also create "many-to-many" relationships by creating a "join" table.
|
||||
For example if you had the following situations:
|
||||
|
||||
- You have a list of `movies`.
|
||||
- A movie can have several `actors`.
|
||||
- An `actor` can perfom in several movies.
|
||||
|
||||
<Tabs
|
||||
defaultValue="SQL"
|
||||
values={[
|
||||
{label: 'SQL', value: 'SQL'},
|
||||
{label: 'Dashboard', value: 'UI'},
|
||||
]}>
|
||||
<TabItem value="SQL">
|
||||
|
||||
```sql
|
||||
create table movies (
|
||||
id bigint generated by default as identity primary key,
|
||||
name text,
|
||||
description text
|
||||
);
|
||||
|
||||
create table actors (
|
||||
id bigint generated by default as identity primary key,
|
||||
name text
|
||||
);
|
||||
|
||||
create table performances (
|
||||
id bigint generated by default as identity primary key,
|
||||
movie_id bigint not null references movies,
|
||||
actor_id bigint not null references actors
|
||||
);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="UI">
|
||||
|
||||
<iframe
|
||||
className="w-full video-with-border"
|
||||
width="640"
|
||||
height="420"
|
||||
src="https://www.youtube-nocookie.com/embed/TKwF3IGij5c"
|
||||
frameBorder="1"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
## Schemas
|
||||
|
||||
Tables belong to `schemas`. Schemas are a way of organizing your tables, often for security reasons.
|
||||
|
||||

|
||||
|
||||
If you don't explicitly pass a schema when creating a table, Postgres will assume that you want to create the table in the `public` schema.
|
||||
|
||||
We can create schemas for organizing tables. For example, we might want a private schema which is hidden from our API:
|
||||
|
||||
|
||||
```sql
|
||||
create schema private;
|
||||
```
|
||||
|
||||
Now we can create tables inside the `private` schema:
|
||||
|
||||
```sql
|
||||
create table salaries (
|
||||
id bigint generated by default as identity primary key,
|
||||
salary bigint not null,
|
||||
actor_id bigint not null references public.actors
|
||||
);
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- [Official Docs: Create table](https://www.postgresql.org/docs/current/sql-createtable.html)
|
||||
- [PostgreSQL Tutorial: Create tables](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-create-table/)
|
||||
- [PostgreSQL Tutorial: Add column](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-add-column/)
|
||||
Reference in new issue
Block a user