PostgreSQL
如何在 PostgreSQL 中创建和删除数据库和表
简介
PostgreSQL和其他关系型数据库管理系统使用数据库和表来组织和结构化数据。我们可以快速回顾这两个术语的定义
在PostgreSQL中,数据库和表之间还有一个中间对象,称为模式(schema)
- 模式(schema):数据库中的一个命名空间,包含表、索引、视图和其他项。
本指南不会直接涉及PostgreSQL的模式概念,但了解它的存在是好的。
相反,我们将重点介绍如何创建和删除PostgreSQL数据库和表。示例将主要使用SQL,但在文章末尾,我们将向您展示如何使用命令行完成其中一些任务。这些替代方法使用的工具包含在标准的PostgreSQL安装中,如果您对PostgreSQL主机具有管理访问权限,则可以使用这些工具。
本指南中涉及的一些语句,特别是PostgreSQL的CREATE TABLE语句,有许多超出本文范围的附加选项。如果您想了解更多信息,请查阅PostgreSQL官方文档。
先决条件
要按照本指南进行操作,您需要使用具有管理权限的用户,通过psql命令行客户端登录到PostgreSQL实例。您的PostgreSQL实例可以是本地安装、远程安装或由提供商提供。
具体来说,您的PostgreSQL用户将需要CREATE DB权限或为Superuser,您可以在psql中使用\du元命令进行检查
\du
List of rolesRole name | Attributes | Member of-----------+------------------------------------------------------------+-----------postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
在安装时自动创建的postgres超级用户拥有所需的权限,但您可以使用任何具有Create DB权限的用户。
创建一个新数据库
连接到PostgreSQL实例后,无论是使用psql还是任何其他SQL客户端,您都可以使用SQL创建数据库。
创建数据库的基本语法是
CREATE DATABASE db_name;
这将使用默认数据库设置,在当前服务器上创建一个名为db_name的数据库,并将当前用户设置为新数据库的所有者。您可以使用以下psql元命令查看默认template1模板的属性
\l template1
List of databasesName | Owner | Encoding | Collate | Ctype | Access privileges-----------+----------+----------+-------------+-------------+-----------------------template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +| | | | | postgres=CTc/postgres(1 row)
您可以添加额外的参数来更改数据库的创建方式。以下是一些常见选项
- ENCODING:设置数据库的字符编码。
- LC_COLLATE:设置数据库的排序规则。这是一个本地化选项,决定了项目在排序时的组织方式。
- LC_CTYPE:设置新数据库的字符分类。这是一个本地化选项,影响哪些字符被视为大写、小写和数字。
这些可以帮助确保数据库能够以您计划支持的格式和您项目的本地化偏好存储数据。
例如,为了确保您的数据库支持Unicode,并覆盖服务器自身的区域设置以使用美式英语本地化(这些碰巧都与上面显示的template1中的值匹配,所以实际上不会发生任何更改),您可以输入
CREATE DATABASE db_nameENCODING 'UTF8'LC_COLLATE 'en_US.UTF-8'LC_CTYPE 'en_US.UTF-8';
为了配合本指南中的示例,请使用实例的默认区域设置和UTF8字符编码创建一个名为school的数据库
CREATE DATABASE school ENCODING 'UTF8';
这将使用您提供的规范创建新数据库。
列出现有数据库
要确定服务器或集群上当前可用的数据库,可以使用以下SQL语句
SELECT datname FROM pg_database;
这将列出当前环境中定义的每个数据库
datname-----------_dodbtemplate1template0defaultdbschool(5 rows)
如前所述,如果您使用psql客户端连接,您还可以使用\l元命令获取此信息
\l
这将显示可用的数据库名称以及它们的拥有者、编码、区域设置和权限
List of databasesName | Owner | Encoding | Collate | Ctype | Access privileges-----------+----------+----------+-------------+-------------+-----------------------_dodb | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |defaultdb | doadmin | UTF8 | en_US.UTF-8 | en_US.UTF-8 |school | doadmin | UTF8 | en_US.UTF-8 | en_US.UTF-8 |template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +| | | | | postgres=CTc/postgrestemplate1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +| | | | | postgres=CTc/postgres(5 rows)
我们创建的school数据库显示在系统中的其他数据库中。这是一个很好的方式来概述服务器或集群中的数据库。
在数据库中创建表
创建一个或多个数据库后,您可以开始定义表来存储数据。表由一个名称和一个定义的模式组成,模式决定了每个记录必须包含的字段和数据类型。
PostgreSQL CREATE TABLE 语法
您可以使用CREATE TABLE语句创建表。该命令的简化基本语法如下
CREATE TABLE table_name (column_name TYPE [column_constraint],[table_constraint,]);
上述语法的组成部分包括以下内容
CREATE TABLE table_name:基本创建语句,表示您希望定义一个表。table_name占位符应替换为您希望使用的表名。column_name TYPE:定义表中的基本列。column_name占位符应替换为您希望用于列的名称。TYPE指定列的PostgreSQL数据类型。存储在表中的数据必须符合列结构和列数据类型才能被接受。column_constraint:列约束是可选的限制,用于对可以存储在列中的数据添加进一步限制。例如,您可以要求条目不能为null、必须唯一或必须为正整数。table_constraints:表约束与列约束类似,但涉及多列的交互。例如,您可以有一个表约束,检查表中的DATE_OF_BIRTH是否在DATE_OF_DEATH之前。
使用IF NOT EXISTS子句有条件地创建表
默认情况下,如果您尝试在PostgreSQL中创建已存在于数据库中的表,则会发生错误。为了解决这个问题,在您希望在表不存在时创建表,但如果它已存在则继续执行的情况下,您可以使用IF NOT EXISTS子句。IF NOT EXISTS是一个可选限定符,它告诉PostgreSQL如果数据库已存在则忽略该语句。
要使用IF NOT EXISTS子句,请将其插入到CREATE TABLE语法之后和表名之前
CREATE TABLE IF NOT EXISTS table_name (column_name TYPE [column_constraint],[table_constraint,]);
这个变体将尝试创建表。如果指定数据库中已存在同名表,PostgreSQL将发出警告,指示表名已被占用,而不是以错误失败。
如何在PostgreSQL中创建表
上述语法足以创建基本表。举例来说,我们将在school数据库中创建两个表。一个表名为supplies,另一个表名为teachers
在supplies表中,我们希望有以下字段
- ID:每种学习用品的唯一ID。
- 名称:特定学习用品的名称。
- 描述:该物品的简短描述。
- 制造商:物品制造商的名称。
- 颜色:物品的颜色。
- 库存:某种学习用品的库存数量。此数量不应小于0。
我们可以使用以下SQL创建具有上述属性的supplies表。
首先,通过键入以下命令切换到您使用psql创建的school数据库
\c school
这将更改我们未来命令的目标数据库。您的提示符应随之改变。
接下来,使用以下语句创建supplies表
CREATE TABLE supplies (id INT PRIMARY KEY,name VARCHAR,description VARCHAR,manufacturer VARCHAR,color VARCHAR,inventory int CHECK (inventory > 0));
这将在school数据库中创建supplies表。PRIMARY KEY列约束是一种特殊约束,用于指示可以唯一标识表中记录的列。因此,该约束指定该列不能为null且必须唯一。PostgreSQL为主键列创建索引以提高查询速度。
通过输入以下命令验证新表是否存在
\dt
List of relationsSchema | Name | Type | Owner--------+----------+-------+---------public | supplies | table | doadmin(1 row)
通过输入以下命令验证模式是否反映了预期的设计
\d supplies
Table "public.supplies"Column | Type | Collation | Nullable | Default--------------+-------------------+-----------+----------+---------id | integer | | not null |name | character varying | | |description | character varying | | |manufacturer | character varying | | |color | character varying | | |inventory | integer | | |Indexes:"supplies_pkey" PRIMARY KEY, btree (id)Check constraints:"supplies_inventory_check" CHECK (inventory > 0)
我们可以看到我们指定的每个列和数据类型。我们为inventory列定义的列约束列在末尾。
接下来,我们将创建一个teachers表。此表中应包含以下列
- 员工ID:唯一的员工识别号。
- 名字:教师的名字。
- 姓氏:教师的姓氏。
- 科目:教师受雇教授的科目。
- 年级:教师受雇教授的学生年级。
使用以下SQL创建具有上述模式的teachers表
CREATE TABLE teachers (id INT PRIMARY KEY,first_name VARCHAR,last_name VARCHAR,subject VARCHAR,grade_level int);
如何使用主键和外键创建表
您可以在我们的其他PostgreSQL指南中找到有关如何使用主键和外键创建表的信息。主键和外键都是PostgreSQL中的数据库约束类型。
主键是一种特殊的列或列组,它保证在同一表中的所有行中都是唯一的。所有主键都可用于唯一标识特定行。主键不仅确保每行对于主键列具有唯一值,还确保这些列不包含NULL值。通常,PostgreSQL中的主键使用以下格式来指定自动分配的递增主键:id SERIAL PRIMARY KEY。
外键是一种确保一个表中的一个或多个列与另一个表中包含的值匹配的方法。这有助于确保表之间的引用完整性。
如何在PostgreSQL中查看表
在PostgreSQL中,您可以根据所需的信息以几种不同的方式列出表。
如果您想查看数据库中可用的表,可以使用psql客户端附带的\dt元命令列出所有表,如我们上面演示的
\dt
List of relationsSchema | Name | Type | Owner--------+----------+-------+---------public | supplies | table | doadminpublic | teachers | table | doadmin(2 rows)
您还可以检查表的模式是否与您的规范匹配
\d teachers
Table "public.teachers"Column | Type | Collation | Nullable | Default-------------+-------------------+-----------+----------+---------id | integer | | not null |first_name | character varying | | |last_name | character varying | | |subject | character varying | | |grade_level | integer | | |Indexes:"teachers_pkey" PRIMARY KEY, btree (id)
teachers表似乎符合我们的定义。
修改表
如果需要更改PostgreSQL中现有表的模式,可以使用ALTER TABLE命令。ALTER TABLE命令与CREATE TABLE命令非常相似,但作用于现有表。
修改表语法
在PostgreSQL中修改表的基本语法如下
ALTER TABLE <table_name> <change_command> <change_parameters>
<change_command>表示您想要进行的具体更改类型,无论是设置不同的表选项、添加或删除列,还是更改类型或约束。<change_parameters>命令部分包含PostgreSQL完成更改所需的任何额外信息。
向表中添加列
您可以使用ADD COLUMN更改命令向PostgreSQL表添加列。更改参数将包括列名、类型和选项,就像您在CREATE TABLE命令中指定它们一样。
例如,要向名为some_table的表添加一个名为missing_column的text类型列,您可以输入
ALTER TABLE some_table ADD COLUMN missing_column text;
从表中删除列
如果您想删除现有列,可以使用DROP COLUMN命令。您需要指定要删除的列的名称作为更改参数
ALTER TABLE some_table DROP COLUMN useless_column;
更改列的数据类型
要更改PostgreSQL用于特定列的数据类型,您可以使用ALTER COLUMN更改命令和SET DATA TYPE列命令。参数包括列名、其新类型,以及一个可选的USING子句,用于指定旧类型如何转换为新类型。
例如,要使用显式转换将resident表中id列的值设置为int,我们可以输入以下内容
ALTER TABLE resident ALTER COLUMN id SET DATA TYPE int USING id::int;
其他表更改
许多其他类型的更改可以通过ALTER TABLE命令实现。有关可用选项的更多信息,请查阅PostgreSQL官方ALTER TABLE文档。
删除表
如果您希望删除表,可以使用DROP TABLE SQL语句。这将删除表以及其中存储的任何数据。
基本语法如下:
DROP TABLE table_name;
如果表存在,这将删除表;如果表名不存在,则会抛出错误。
如果您希望在表存在时删除它,在表不存在时不做任何操作,可以在语句中包含IF EXISTS限定符
DROP TABLE IF EXISTS table_name;
默认情况下,具有其他表或对象依赖关系的表不能在这些依赖关系存在时被删除。为了避免错误,您可以选择包含CASCADE参数,该参数会自动删除表及其任何依赖关系
DROP TABLE table_name CASCADE;
如果任何表具有引用您正在删除的表的外键约束,该约束将自动被删除。
通过输入以下命令删除我们之前创建的supplies表
DROP TABLE supplies;
我们将保留teachers数据库,以演示删除数据库的语句也会删除所有子对象(如表)。
删除数据库
DROP DATABASE语句指示PostgreSQL删除指定的数据库。基本语法如下
DROP DATABASE database_name;
将database_name占位符替换为您希望删除的数据库名称。如果找到该数据库,则会将其删除。如果找不到该数据库,则会发生错误
DROP DATABASE some_database;
ERROR: database "some_database" does not exist
如果您希望在数据库存在时删除它,否则不做任何操作,请包含可选的IF EXISTS选项
DROP DATABASE IF EXISTS some_database;
NOTICE: database "some_database" does not exist, skippingDROP DATABASE
这将删除数据库,或者在找不到数据库时不做任何操作。
要删除本指南中使用的school数据库,请列出系统上现有的数据库
\l
List of databasesName | Owner | Encoding | Collate | Ctype | Access privileges-----------+----------+----------+-------------+-------------+-----------------------_dodb | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |defaultdb | doadmin | UTF8 | en_US.UTF-8 | en_US.UTF-8 |school | doadmin | UTF8 | en_US.UTF-8 | en_US.UTF-8 |template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +| | | | | postgres=CTc/postgrestemplate1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +| | | | | postgres=CTc/postgres(5 rows)
打开与您不想删除的其中一个数据库的新连接
\c defaultdb
新连接打开后,使用以下命令删除school数据库
DROP DATABASE school;
这将删除school数据库以及其中定义的teachers表。
如果您一直使用SQL进行操作,您可以在此处结束或跳到结论。如果您想了解如何从命令行创建和删除数据库,请继续阅读下一节。
使用管理命令行工具创建和删除数据库
如果您对安装PostgreSQL的服务器或集群具有shell访问权限,您可能可以使用一些额外的命令行工具来帮助创建和删除数据库。createdb和dropdb命令在安装PostgreSQL时会一并捆绑。
从命令行创建新数据库
createdb命令的基本语法(应由具有PostgreSQL管理员权限的系统用户运行)是
createdb db_name
这将使用默认设置在PostgreSQL中创建一个名为db_name的数据库。
该命令还接受选项来改变其行为,就像您之前看到的SQL变体一样。您可以通过man createdb了解更多关于这些选项的信息。一些最重要的选项是
这些可以帮助确保数据库能够以您计划支持的格式和您项目的本地化偏好存储数据。
例如,为了确保您的数据库支持Unicode,并覆盖服务器自身的区域设置以使用美式英语本地化,您可以输入
createdb --encoding=UTF8 --locale=en_US db_name
假设您有正确的权限,数据库将根据您的规范创建。
为了配合本指南中的示例,您可以通过输入以下命令创建一个名为school的数据库,使用默认区域设置和UTF8字符编码
createdb --encoding=UTF8 school
然后,您可以使用psql连接到数据库以照常设置表。
从命令行删除数据库
dropdb命令镜像了DROP DATABASE SQL语句。它具有以下基本语法
dropdb database_name
将database_name占位符更改为引用您希望删除的数据库。
默认情况下,如果找不到指定的数据库,此命令将导致错误。为了避免这种情况,您可以包含可选的--if-exists标志
dropdb --if-exists database_name
这将删除指定的数据库(如果存在)。否则,它将不做任何操作。
要删除我们之前创建的school数据库,请键入
dropdb school
这将删除数据库和其中的任何子元素,例如表。
结论
本文介绍了如何在PostgreSQL中创建和删除数据库和表的基础知识。这些是设置数据库系统并开始定义数据结构所需的一些最基本的命令。
如前所述,本PostgreSQL教程中涵盖的SQL语句,特别是CREATE TABLE语句,有许多额外的参数可用于更改PostgreSQL的行为。您可以通过查阅PostgreSQL官方文档来了解更多信息。
当使用Prisma开发PostgreSQL时,您通常会使用Prisma Migrate创建数据库和表。您可以在我们的使用Prisma Migrate进行开发指南中学习如何使用它。
常见问题解答
是的,PostgreSQL在创建数据库和表时都支持使用IF NOT EXISTS。以下演示了在创建表时使用该子句。
CREATE TABLE IF NOT EXISTS table_name (column_name TYPE [column_constraint],[table_constraint,]);
要从转储文件(pg_dump)创建数据库,PostgreSQL提供了实用程序pg_restore。
该程序将数据库重建为转储时的相同状态。示例语法如下
pg_restore [connection-option...][option...][filename]
要在PostgreSQL中创建数据库,请使用createdb命令。语法如下
createdb db_name
DROP DATABASE语句指示PostgreSQL删除指定的数据库。基本语法如下
DROP DATABASE database_name;
要更改特定列的数据类型,请使用带有SET DATA TYPE列命令的ALTER COLUMN更改命令。
基本语法包括列名、新类型以及一个可选的USING子句,用于指定旧类型的转换方式。
ALTER TABLE resident ALTER COLUMN id SET DATA TYPE int USING id::int;


