前序篇,主要是对 PostgreSQL
默认的几个数据库进行说明、介绍下每个库的用途等等。后续章节在使用这些默认库时,不在逐一说明了。
默认库
首先,当数据库安装完成之后,执行\l
(L字母的小写)可以看到数据库清单,如下:
-- 如下 \l 其后是没有加号(+)
postgres=# \l
postgres | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |
template0 | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
postgres=#
-- 注意:这里执行的命令有一个加号(+),可以看到更多的一些信息.
postgres=# \l+
postgres | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | | 7941 kB | pg_default | default administrative connection database
template0 | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/postgres +| 7737 kB | pg_default | unmodifiable empty database
| | | | | postgres=CTc/postgres | | |
template1 | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/postgres +| 7925 kB | pg_default | default template for new databases
| | | | | postgres=CTc/postgres | | |
postgres=#
以下是 \l+
命令:每一列的含义解释:
Name
:数据库的名称。Owner
:数据库所有者的名称。Encoding
:数据库的字符编码。Collate
:数据库的排序规则(Collation)。Ctype
:数据库的字符分类(Character Classification)。Access privileges
:对数据库的访问权限。Size
:数据库占用的磁盘空间大小。Tablespace
:表空间(Tablespace)的名称。Description
:数据库的描述信息。
在输出的结果中,每一行表示一个数据库,每一列对应于数据库的不同属性。
例如,第一行表示postgres
数据库,它的所有者是postgres
,使用的字符编码是UTF8
,排序规则和字符分类也是zh_CN.UTF-8
,占用的磁盘空间为7941 kB
,没有指定表空间,且具有默认的访问权限等。
从上述的查询结果中,可以看出:安装完成后会默认创建以下几个数据库:
-
postgres
:这是默认的管理数据库,用于管理 PostgreSQL 服务器和用户角色。它包含了用于管理服务器和用户的系统表,例如pg_roles
、pg_database
等。通常不建议用于存储实际数据,而是用于管理目的。 -
template0
:这是一个空模板数据库,用于创建其他数据库的模板。它作为创建新数据库的模板,但是不允许对其进行更改,以确保其始终是一个空数据库。 -
template1
:与 template0 类似,也是一个模板数据库,用于创建其他数据库的模板。但与 template0 不同的是,template1 是可以被修改的,可以在其中创建用户自定义的对象,例如函数、表等。通常情况下,我们可以在 template1 中创建通用的配置、用户、函数等,以便在创建新数据库时能够从 template1 中继承这些配置。
模板库
在上述的 默认库 中,提到了 管理数据库、模板数据库(template0
、template1
),
管理数据库 很好理解:就是存放了一些数据库系统层面的视图(pg_roles等等)的库,用于管理数据库,类似 MySQL 中的 sys、information_schema 等这类库。
那么,什么是模板数据库??
再说 模板数据库 之前,先看如下一个示例:
- 分别切换至
template0
、template1
,查看其内,是否有表?
=> 查看结果:无其他表.
=> 注意:切换至template0
时,切换失败了。(后续会说明原因为什么不能切)
-- 切换失败了(暂时先跳过,尝试切换 template1 )
postgres=# \c template0
FATAL: database "template0" is not currently accepting connections
Previous connection kept
postgres=#
-- 切换 至 template1 中
postgres=# \c template1
You are now connected to database "template1" as user "postgres".
-- 查看发现:没有表
template1=# \d
Did not find any relations.
template1=#
- 创建数据库
testdb01
,并查看期内有哪些表?
-- 创建 testdb01 数据库
postgres=# create database testdb01;
CREATE DATABASE
postgres=#
-- 查看有哪些表?
-- => 查看结果:无表.
template1=# \c testdb01;
You are now connected to database "testdb01" as user "postgres".
testdb01=#
testdb01=# \d
Did not find any relations.
testdb01=#
- 再次切换到
template1
库中,创建client
表(这张表自定义测试用的)
-- 切换到 template1 库
postgres=# \c template1
You are now connected to database "template1" as user "postgres".
template1=#
-- 创建 client 表
template1=# CREATE TABLE client (
template1(# client_id SERIAL PRIMARY KEY,
template1(# client_name VARCHAR(100),
template1(# contact_name VARCHAR(100),
template1(# email VARCHAR(100),
template1(# phone VARCHAR(20)
template1(# );
CREATE TABLE
template1=#
- 创建
testdb02
数据库,并查看期内是否有表?
-- 当前数据库 template1 ,查看其内 client 表已经创建成功.
template1=# \d
public | client | table | postgres
public | client_client_id_seq | sequence | postgres
-- 创建 testdb02 库
template1=# create database testdb02;
CREATE DATABASE
-- 切换至 testdb02 库
template1=# \c testdb02;
You are now connected to database "testdb02" as user "postgres".
-- 查看 testdb02 库,发现:其内也有 client 表.
testdb02=# \d
public | client | table | postgres
public | client_client_id_seq | sequence | postgres
testdb02=#
猜测 :创建的数据库和
template0
、template1
存在某种关系;现template1
发生改变(创建 client 表),那之前创建的testdb01
库中,是否也有 client 表?或者在创建一个新的testdb03
库,是否会有 client 表?
检测猜想:
-- 切回到 testdb01 库,查看是否有 client 表?
-- => 发现:无表.
testdb02=# \c testdb01
You are now connected to database "testdb01" as user "postgres".
testdb01=#
testdb01=# \d
Did not find any relations.
testdb01=#
-- 创建新的数据库 testdb03
testdb01=# create database testdb03;
CREATE DATABASE
-- 切换到新库 testdb03,检查是否有 client 表?
-- => 发现:有 client 表.
testdb01=# \c testdb03
You are now connected to database "testdb03" as user "postgres".
testdb03=#
testdb03=# \d
public | client | table | postgres
public | client_client_id_seq | sequence | postgres
testdb03=#
那在猜测一下:若将
template1
中的 client 表删除,再次创建数据库 testdb04 ,其内是否会有 client 表??
自行测试一下哈~
通过上面的示例,不难看出,创建数据库时,实际上是通过复制一个已有数据库进行的。在默认情况下,将复制 template1
这个数据库,换言之:此数据库(template1
)是创建其他新数据库的一个模板。
那回到最初的问题:什么是模板数据库?? 这个问题也就迎刃而解了。
补充说明:如果给 template1
增加一些对象(例如:添加表),那么这些对象将被复制到后续创建的新库中。
Q
:
在上述展示的默认库中,除了 template1
模板库之外,还有一个 template0
,它又是弄啥嘞?(它又是做什么用的?)、和 template1
有什么区别?
A
:
template0
和 template1
是两个特殊的模板数据库,用于创建新数据库时作为模板。它们之间的区别在于:
-
template0:
template0
是一个严格意义上的空模板数据库,其中不包含任何用户自定义的对象。它只包含了必要的系统表和系统视图,用于创建新数据库时提供一个纯净的模板。- 由于
template0
是一个纯净的模板,用户不能在其中创建任何对象或修改其中的内容。即使是超级用户也不能在template0
中进行修改。
-
template1:
template1
也是一个模板数据库,但它允许用户在其中创建用户自定义的对象,例如表、函数、视图等。当创建新数据库时,默认情况下会从template1
复制数据库结构和内容。template1
的内容可以由用户自行修改,例如可以在其中创建通用的配置、用户、函数等对象,以便在创建新数据库时能够从template1
中继承这些配置。
总的来说,template0
是一个纯净的、只读的空模板数据库,而 template1
是一个可修改的模板数据库,用户可以在其中创建自定义对象。通常情况下,建议不要修改 template0
,而是在 template1
中进行用户自定义的操作。
除了上述的区别之外,你可能会举手
发言:补充另外一个区别:
template0
不能切换,template1
可以切换。
其实,这个算不上区别(个人理解)。因为是否可以切换、是“进行了属性设置的”。
现进行说明下:
Q
: 为什么不能切换至template0
库,而可以切换至 template1
库?
A
: 执行如下 SQL,查看数据库一些属性信息(datistemplate, datallowconn).
postgres=# select oid, datname, datistemplate, datallowconn from pg_database;
13580 | postgres | f | t
1 | template1 | t | t
13579 | template0 | t | f --看到这个属性了吧!是 False。。。人家 template1的属性是 True.
24603 | testdb01 | f | t
24613 | testdb02 | f | t
24614 | testdb03 | f | t
postgres=#
部分属性列的含义:
-
datistemplate
:- 这个列用于标识数据库是否是一个模板数据库(template database)。
- 如果
datistemplate
的值为true
,则表示该数据库是一个模板数据库,可以作为其他数据库的模板来创建。 - 如果
datistemplate
的值为false
,则表示该数据库不是模板数据库,不能用作其他数据库的模板。
-
datallowconn
:- 这个列用于标识数据库是否允许客户端连接(allow connections)。
- 如果
datallowconn
的值为true
,则表示该数据库允许客户端连接,可以对其进行查询和操作。 - 如果
datallowconn
的值为false
,则表示该数据库不允许客户端连接,通常是一些系统数据库或模板数据库。