⌘+k ctrl+k
1.1.3 (stable)
Search Shortcut cmd + k | ctrl + k
CREATE TABLE Statement

CREATE TABLE 语句在目录中创建一个表。

Examples

创建一个包含两个整数列的表(ij):

CREATE TABLE t1 (i INTEGER, j INTEGER);

创建一个带有主键的表:

CREATE TABLE t1 (id INTEGER PRIMARY KEY, j VARCHAR);

创建一个带有复合主键的表:

CREATE TABLE t1 (id INTEGER, j VARCHAR, PRIMARY KEY (id, j));

创建一个包含各种不同类型和约束的表:

CREATE TABLE t1 (
    i INTEGER NOT NULL,
    decimalnr DOUBLE CHECK (decimalnr < 10),
    date DATE UNIQUE,
    time TIMESTAMP
);

使用CREATE TABLE ... AS SELECT (CTAS)创建表:

CREATE TABLE t1 AS
    SELECT 42 AS i, 84 AS j;

从CSV文件创建表格(自动检测列名和类型):

CREATE TABLE t1 AS
    SELECT *
    FROM read_csv('path/file.csv');

我们可以使用FROM-first语法来省略SELECT *

CREATE TABLE t1 AS
    FROM read_csv('path/file.csv');

t2的模式复制到t1

CREATE TABLE t1 AS
    FROM t2
    LIMIT 0;

临时表

可以使用CREATE TEMP TABLECREATE TEMPORARY TABLE语句创建临时表(见下图)。 临时表是会话范围的(例如类似于PostgreSQL),这意味着只有创建它们的特定连接才能访问它们,一旦与DuckDB的连接关闭,它们将自动删除。 临时表驻留在内存中而不是磁盘上(即使连接到持久化的DuckDB时也是如此),但如果连接时或使用SET命令设置了temp_directory 配置,当内存受限时,数据将溢出到磁盘。

从CSV文件创建一个临时表(自动检测列名和类型):

CREATE TEMP TABLE t1 AS
    SELECT *
    FROM read_csv('path/file.csv');

允许临时表将多余的内存卸载到磁盘:

SET temp_directory = '/path/to/directory/';

临时表是temp.main模式的一部分。虽然不推荐,但它们的名称可能与常规数据库表的名称重叠。在这些情况下,请使用它们的完全限定名称,例如temp.main.t1,以消除歧义。

CREATE OR REPLACE

CREATE OR REPLACE 语法允许创建一个新表或用一个新表覆盖现有表。这是删除现有表然后创建新表的简写形式。

创建一个包含两个整数列(i 和 j)的表,即使 t1 已经存在:

CREATE OR REPLACE TABLE t1 (i INTEGER, j INTEGER);

IF NOT EXISTS

IF NOT EXISTS 语法仅在表不存在时才会继续创建表。如果表已经存在,则不会采取任何操作,现有的表将保留在数据库中。

创建一个包含两个整数列(ij)的表,仅当 t1 尚不存在时:

CREATE TABLE IF NOT EXISTS t1 (i INTEGER, j INTEGER);

CREATE TABLE ... AS SELECT (CTAS)

DuckDB 支持 CREATE TABLE ... AS SELECT 语法,也称为“CTAS”:

CREATE TABLE nums AS
    SELECT i
    FROM range(0, 3) t(i);

此语法可以与CSV阅读器结合使用,直接从CSV文件中读取而不需要指定函数的简写,FROM-first语法,以及HTTP(S)支持,产生简洁的SQL命令,如下所示:

CREATE TABLE flights AS
    FROM 'https://duckdb.org/data/flights.csv';

CTAS 构造也可以与 OR REPLACE 修饰符一起使用,生成 CREATE OR REPLACE TABLE ... AS 语句:

CREATE OR REPLACE TABLE flights AS
    FROM 'https://duckdb.org/data/flights.csv';

请注意,无法使用带有约束(主键、检查约束等)的CTAS语句创建表。

检查约束

一个CHECK约束是一个表达式,必须由表中每一行的值来满足。

CREATE TABLE t1 (
    id INTEGER PRIMARY KEY,
    percentage INTEGER CHECK (0 <= percentage AND percentage <= 100)
);
INSERT INTO t1 VALUES (1, 5);
INSERT INTO t1 VALUES (2, -1);
Constraint Error: CHECK constraint failed: t1
INSERT INTO t1 VALUES (3, 101);
Constraint Error: CHECK constraint failed: t1
CREATE TABLE t2 (id INTEGER PRIMARY KEY, x INTEGER, y INTEGER CHECK (x < y));
INSERT INTO t2 VALUES (1, 5, 10);
INSERT INTO t2 VALUES (2, 5, 3);
Constraint Error: CHECK constraint failed: t2

CHECK 约束也可以作为 CONSTRAINTS 子句的一部分添加:

CREATE TABLE t3 (
    id INTEGER PRIMARY KEY,
    x INTEGER,
    y INTEGER,
    CONSTRAINT x_smaller_than_y CHECK (x < y)
);
INSERT INTO t3 VALUES (1, 5, 10);
INSERT INTO t3 VALUES (2, 5, 3);
Constraint Error: CHECK constraint failed: t3

外键约束

一个FOREIGN KEY是一个列(或一组列),它引用另一个表的主键。外键检查引用完整性,即在插入时,被引用的主键必须存在于另一个表中。

CREATE TABLE t1 (id INTEGER PRIMARY KEY, j VARCHAR);
CREATE TABLE t2 (
    id INTEGER PRIMARY KEY,
    t1_id INTEGER,
    FOREIGN KEY (t1_id) REFERENCES t1 (id)
);

示例:

INSERT INTO t1 VALUES (1, 'a');
INSERT INTO t2 VALUES (1, 1);
INSERT INTO t2 VALUES (2, 2);
Constraint Error: Violates foreign key constraint because key "id: 2" does not exist in the referenced table

可以在复合主键上定义外键:

CREATE TABLE t3 (id INTEGER, j VARCHAR, PRIMARY KEY (id, j));
CREATE TABLE t4 (
    id INTEGER PRIMARY KEY, t3_id INTEGER, t3_j VARCHAR,
    FOREIGN KEY (t3_id, t3_j) REFERENCES t3(id, j)
);

示例:

INSERT INTO t3 VALUES (1, 'a');
INSERT INTO t4 VALUES (1, 1, 'a');
INSERT INTO t4 VALUES (2, 1, 'b');
Constraint Error: Violates foreign key constraint because key "id: 1, j: b" does not exist in the referenced table

外键也可以在唯一列上定义:

CREATE TABLE t5 (id INTEGER UNIQUE, j VARCHAR);
CREATE TABLE t6 (
    id INTEGER PRIMARY KEY,
    t5_id INTEGER,
    FOREIGN KEY (t5_id) REFERENCES t5(id)
);

Limitations

外键有以下限制。

不支持带有级联删除的外键(FOREIGN KEY ... REFERENCES ... ON DELETE CASCADE)。

目前不支持插入具有自引用外键的表,这将导致以下错误:

Constraint Error: Violates foreign key constraint because key "..." does not exist in the referenced table.

生成列

[type] [GENERATED ALWAYS] AS (expr) [VIRTUAL|STORED] 语法将创建一个生成列。这种列中的数据是从其表达式中生成的,该表达式可以引用表的其他(常规或生成的)列。由于它们是通过计算生成的,因此这些列不能直接插入数据。

DuckDB 可以根据表达式的返回类型推断生成列的类型。这允许您在声明生成列时省略类型。可以显式设置类型,但如果无法将类型转换为生成列的类型,则插入引用列可能会失败。

生成的列有两种类型:VIRTUALSTORED。 虚拟生成列的数据不存储在磁盘上,而是在每次引用该列时(通过选择语句)从表达式中计算出来。

存储生成列的数据存储在磁盘上,并且每次其依赖项的数据发生变化时(通过INSERT / UPDATE / DROP语句)都会重新计算。

目前,仅支持VIRTUAL类型,如果最后一个字段留空,它也是默认选项。

生成列的最简单语法:

类型是从表达式中派生的,变体默认为 VIRTUAL

CREATE TABLE t1 (x FLOAT, two_x AS (2 * x));

为了完整性,完全指定相同的生成列:

CREATE TABLE t1 (x FLOAT, two_x FLOAT GENERATED ALWAYS AS (2 * x) VIRTUAL);

Syntax