PostgreSQL 管理数据表(一)

创建表

在PostgreSQL中,使用CREATE TABLE语句创建一个新表:

CREATE TABLE table_name
(
    column_name data_type column_constraint,
    column_name data_type,
     ...,
    table_constraint
);

建表语句说明

  • 首先,table_name指定了新表的名称。
  • 括号内是字段的定义,column_name是字段的名称,data_type是它的类型,column_constraint是可选的字段约束;多个字段使用逗号进行分隔。
  • 最后,table_constraint是可选的表级约束

建表示例

CREATE TABLE departments
(
    department_id   INTEGER               NOT NULL PRIMARY KEY,
    department_name CHARACTER VARYING(30) NOT NULL
);

以上语句创建了一个新的部门表(departments)。它包含两个字段,部门编号(dept_id)是一个整数类型(INTEGER),字段的值不可以为空(NOT NULL),同时它还是这个表的主键(PRIMARY KEY);部门编号(dept_name)是一个可变长度的字符串,也不允许为空。

PostgreSQL提供了丰富的内置数据类型,同时还允许用户自定义数据类型。最常见的基本数据类型包括:

  • 字符类型,包括定长字符串CHAR(n),变长字符串VARCHAR(n),以及支持更大长度的字符串TEXT。
  • 数字类型,包括整数类型SMALLINT、INTEGER、BIGINT,精确数字NUMERIC (p, s),浮点数REAL、DOUBLE PRECISION。
  • 时间类型,包括日期DATE、时间TIME、时间戳TIMESTAMP。

PostgreSQL支持SQL标准中的所有字段约束和表约束。其中,字段约束包括:

  • NOT NULL,非空约束,该字段的值不能为空(NULL);
  • UNIQUE,唯一约束,该字段每一行的值不能重复。不过,PostgreSQL允许该字段存在多个NULL值,并且将它们看作不同的值。需要注意的是SQL标准只允许UNIQUE字段中存在一个NULL值;
  • PRIMARY KEY,主键约束,包含了NOT NULL约束和UNIQUE约束。如果主键只包含一个字段,可以通过列级约束进行定义(参考上面的示例);但是如果主键包含多个字段(复合主键)或者需要为主键指定一个自定义的名称,需要使用表级约束进行定义(参见下文示例);
  • REFERENCES,外键约束,字段中的值必需已经在另一个表中存在。外键用于定义两个表之间的参照完整性(referential integrity),例如,员工的部门编号字段必须是一个已经存在的部门;
  • CHECK,检查约束,插入或更新数据时检查数据是否满足某个条件。例如,产品的价格必需大于零;
  • DEFAULT,默认值,插入数据时,如果没有为这种列指定值,系统将会使用默认值代替;

表级约束和字段约束类似,只不过它是基于整个表定义的约束,还能够为约束指定自定义的名称。PostgreSQL支持的表级约束包括

  • UNIQUE(column1, ...),唯一约束,括号中的字段值或字段值的组合必须唯一。
  • PRIMARY KEY(column1, ...),主键约束,定义主键或者复合主键。
  • REFERENCES,定义外键约束。
  • CHECK,定义检查约束。

以下示例创建了员工表(employees)

CREATE TABLE employees
(
    employee_id    INTEGER               NOT NULL,
    first_name     CHARACTER VARYING(20),
    last_name      CHARACTER VARYING(25) NOT NULL,
    email          CHARACTER VARYING(25) NOT NULL,
    phone_number   CHARACTER VARYING(20),
    hire_date      DATE                  NOT NULL,
    salary         NUMERIC(8, 2),
    commission_pct NUMERIC(2, 2),
    manager_id     INTEGER,
    department_id  INTEGER,
    CONSTRAINT emp_emp_id_pk PRIMARY KEY (employee_id),
    CONSTRAINT emp_salary_min CHECK (salary > 0),
    CONSTRAINT emp_email_uk UNIQUE (email),
    CONSTRAINT emp_dept_fk FOREIGN KEY (department_id) REFERENCES departments (department_id),
    CONSTRAINT emp_manager_fk FOREIGN KEY (manager_id) REFERENCES employees (employee_id)
);
员工表包含以下字段和约束:
  • employee_id,员工编号,整数类型,主键(通过表级约束为主键指定了名称 emp_emp_id_pk);
  • first_name,名字,字符串;
  • last_name,姓氏,字符串,不能为空;
  • email,电子邮箱,字符串,不能为空,必须唯一(emp_email_uk);
  • phone_number,电话号码,字符串;
  • hire_date,雇佣日期,日期类型,不能为空;
  • salary,薪水,数字类型,必须大于零(emp_salary_min);
  • commission_pct,佣金百分比,数字类型;
  • manager_id,经理编号,外键(通过外键emp_manager_fk引用员工表的员工编号);
  • department_id,部门编号,外键(通过外键emp_dept_fk引用部门表departments的编号department_id)
下图是这两个表的实体关系图

 除了自己定义表的结构之外,PostgreSQL还提供了另一个创建表的方法,就是通过一个查询的结果创建新表:

CREATE TABLE table_name AS query;
或
SELECT ...INTO new_table FROM ...;

例如,可以基于employees复制出两个新的表:

CREATE TABLE emp1 AS SELECT * FROM employees;
SELECT * INTO emp2 FROM employees;

模式搜索路径

在PostgreSQL中,表属于某个模式(schema)。当我们创建表时,更完整的语法应该是

CREATE TABLE schema_name.table_name...

访问表的时候也是一样。但是刚才在前面创建示例表的时候,并没有加上模式名称的限定。这里涉及到一个模式的搜索路径概念。现在先看一下当前的搜索路径

test=# show search_path;
   search_path   
-----------------
 "$user", public
(1 row)

搜索路径是一个逗号分隔的模式名称。当使用表的时候,PostgreSQL会依次在这些模式中进行查找,返回第一个匹配的表名;当创建一个新表时,如果没有指定模式名称,PostgreSQL会在第一个模式中进行创建。第一个模式默认为当前用户名,如果不存在该模式,使用后面的公共模式(public)

test=# select user;
   user   
----------
 postgres
(1 row)
test=# \dn
  List of schemas
  Name  |  Owner   
--------+----------
 hr     | wdh
 public | postgres

当前用户名为postgres,但是不存在名为postgres的模式,因此我们创建的表会位public模式中

test=# \d
            List of relations
 Schema |    Name     | Type  |  Owner   
--------+-------------+-------+----------
 public | departments | table | postgres
 public | employees   | table | postgres

可以通过SET命令修改默认的搜索路径:

test=# SET search_path TO hr,public;

此时,如果我们再创建新表而不指定模式名称时,默认会在模式hr中创建。除了表之外,其他的模式对象,例如索引、函数、类型等等,也遵循相同的原则。

posted @ 2023-07-05 10:16  晓枫的春天  阅读(171)  评论(0编辑  收藏  举报