Table of Contents
本章介绍如何创建用于保存数据的数据库结构。在关系数据库中,原始数据存储在表中,因此本章的大部分内容都在说明如何创建和修改表,以及有哪些特性可用于控制表中存储的数据。随后,我们将讨论如何把表组织到模式中,以及如何向表分配权限。最后,我们会简要介绍一些同样会影响数据存储的特性,例如继承、表分区、视图、函数和触发器。
关系数据库中的表很像纸面上的表格:它由行和列组成。列的数量和顺序是固定的,每一列都有名称。行的数量则是可变的,它反映了某一时刻存储了多少数据。SQL 不对表中行的顺序作任何保证。读取表时,除非显式要求排序,否则行会以未指定的顺序出现,参见Chapter 7。此外,SQL 不会为行分配唯一标识符,因此一个表中可能出现多行完全相同的记录。这是 SQL 所依据的数学模型带来的结果,但通常并不理想。本章稍后将看到如何处理这个问题。
每一列都有一种数据类型。数据类型限制了可以赋给该列的可能值集合,并为列中存储的数据赋予语义,从而使其能够用于计算。例如,声明为数值类型的列不能接受任意文本字符串,存储在这类列中的数据可以参与数学运算。相比之下,声明为字符串类型的列几乎能接受任何种类的数据,但并不适合用于数学计算,尽管仍可进行字符串拼接等其他操作。
PostgreSQL提供了相当丰富的一组内置数据类型,适用于许多应用场景。用户也可以定义自己的数据类型。大多数内置数据类型的名称和语义都很直观,因此我们把详细说明留到Chapter 8。一些常用的数据类型包括:表示整数的integer、表示可能带小数部分数值的numeric、表示字符串的text、表示日期的date、表示一天中时间值的time,以及同时包含日期和时间的timestamp。
要创建一个表,可使用名副其实的CREATE TABLE命令。在该命令中,至少要指定新表的名称、各列的名称以及每列的数据类型。例如:
CREATE TABLE my_first_table (
first_column text,
second_column integer
);
这会创建一个名为my_first_table的表,它有两列。第一列名为first_column,数据类型为text;第二列名为second_column,类型为integer。表名和列名遵循Section 4.1.1中解释的标识符语法。类型名通常也是标识符,但也有少数例外。注意,列列表以逗号分隔,并用圆括号括起来。
当然,前面的例子相当刻意。通常,你会为表和列起能体现其所存储数据含义的名称。下面看一个更实际的例子:
CREATE TABLE products (
product_no integer,
name text,
price numeric
);
(numeric类型可以存储小数部分,这对金额很常见。)
在创建许多相互关联的表时,最好为表和列选择一致的命名模式。例如,表名可以使用单数名词或复数名词,两种做法都各有支持者。
一个表能包含的列数是有限的。根据列类型不同,这个上限在 250 到 1600 之间。不过,定义一个接近这个数量的表极不常见,而且其设计往往值得商榷。
如果不再需要某个表,可以使用DROP TABLE命令删除它。例如:
DROP TABLE my_first_table; DROP TABLE products;
尝试删除不存在的表会报错。不过,在 SQL 脚本文件中,人们常常在创建每个表之前无条件地尝试删除它,并忽略可能出现的错误消息,这样脚本无论表是否存在都能工作。(如果愿意,也可以使用DROP TABLE IF EXISTS变体来避免错误消息,但这不是标准 SQL。)
如果我们需要修改一个已经存在的表,请参考本章稍后的Section 5.7。
利用到目前为止所讨论的工具,我们已经可以创建功能完备的表。本章其余内容关注如何向表定义添加特性,以确保数据完整性、安全性或使用便利。如果你现在就急着向表中填充数据,可以先跳到Chapter 6,稍后再回来阅读本章其余内容。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。