数据表在刚创建完成时是一个空表。在数据库能够提供实际业务价值之前,首要任务是向其中写入数据。数据以整行为最小单位进行写入。你可以在单条命令中一次性写入多行数据,但无论如何都不可能写入一个不完整的数据行。即使在业务上当前只掌握了部分字段的具体取值,系统在底层构建的依然是一个完整的物理行。
写入新数据行使用 INSERT 命令。该命令要求明确指定目标表名以及各个字段的具体取值。例如回顾在 Chapter 5 中创建的商品表:
CREATE TABLE products (
product_no integer,
name text,
price numeric
);
向该表插入一条记录的基础命令为:
INSERT INTO products VALUES (1, 'Cheese', 9.99);
数据值按照字段在建表定义中出现的先后顺序排列,各值之间使用逗号分隔。通常情况下传入的值是字面常量,但此处完全允许编写任意动态标量表达式。
上述基础语法的不足之处在于你必须硬性记住数据表中字段的绝对顺序。为规避这一风险,可以在命令中显式声明目标字段列表。例如,以下两条语句与上述命令的效果完全一致:
INSERT INTO products (product_no, name, price) VALUES (1, 'Cheese', 9.99);
INSERT INTO products (name, price, product_no) VALUES ('Cheese', 9.99, 1);
在生产工程实践中,始终显式声明字段列表被公认为优秀的编码习惯。
如果你在写入时并不具备全部字段的数据值,可以显式省略未赋值的字段。此时被省略的字段将被系统自动填充为各自预设的默认值:
INSERT INTO products (product_no, name) VALUES (1, 'Cheese'); INSERT INTO products VALUES (1, 'Cheese');
第二种写法属于 PostgreSQL 的语法扩展。它会自左向右依次填充所给定的若干字段,剩余未匹配的尾部字段全部自动置为默认值。
为了语义清晰,你也可以在输入列表中显式使用关键字 DEFAULT 请求赋予默认值,无论是针对单个字段还是针对整行:
INSERT INTO products (product_no, name, price) VALUES (1, 'Cheese', DEFAULT); INSERT INTO products DEFAULT VALUES;
支持在单条命令中批量插入多条数据行:
INSERT INTO products (product_no, name, price) VALUES
(1, 'Cheese', 9.99),
(2, 'Bread', 1.99),
(3, 'Milk', 2.99);
还可以直接将查询语句的返回结果集插入到目标表中(结果集可以是空集、单行或海量多行):
INSERT INTO products (product_no, name, price)
SELECT product_no, name, price FROM new_products
WHERE release_date = 'today';
这充分发挥了 SQL 查询引擎(Chapter 7)的强大能力,能够基于复杂的业务计算动态组装待写入的数据。
在需要单次导入海量巨量数据时,建议使用 COPY 命令。它虽然不像 INSERT 那样支持灵活的计算表达式,但在底层做了批量读写优化,性能远高于单条插入。关于如何调优大批量导入性能,详见 Section 14.4。