15.2. Lesson: 实现数据模型
现在我们已经讨论了所有的理论,让我们创建一个新的数据库。这个数据库将被用来为后面的课程做练习。
The goal for this lesson: 安装所需的软件并使用它来实现我们的示例数据库。
15.2.1. 安装PostgreSQL
备注
您可以在https://www.postgresql.org/download/.上找到适用于您的操作系统的PostgreSQL包和安装说明请注意,文档将假设用户在Ubuntu下运行QGIS。
在Ubuntu下:
sudo apt install postgresql-9.1
您应该会收到这样的消息:
[sudo] password for qgis:
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
postgresql-client-9.1 postgresql-client-common postgresql-common
Suggested packages:
oidentd ident-server postgresql-doc-9.1
The following NEW packages will be installed:
postgresql-9.1 postgresql-client-9.1 postgresql-client-common postgresql-common
0 upgraded, 4 newly installed, 0 to remove and 5 not upgraded.
Need to get 5,012kB of archives.
After this operation, 19.0MB of additional disk space will be used.
Do you want to continue [Y/n]?
新闻发布会 Y 和 Enter 并等待下载和安装完成。
15.2.2. 帮助
PostgreSQL有非常好的 online 文件。
15.2.3. 创建数据库用户
在Ubuntu下:
安装完成后,运行以下命令以成为postgres用户,然后创建一个新的数据库用户:
sudo su - postgres
出现提示时,输入您的正常登录密码(您需要具有sudo权限)。
现在,在postgres用户的bash提示符下,创建数据库用户。确保用户名与您的Unix登录名匹配:这将使您的工作更轻松,因为当您以该用户身份登录时,Postgres将自动验证您的身份:
createuser -d -E -i -l -P -r -s qgis
出现提示时,请输入密码。您应该使用与您的登录密码不同的密码。
这些选项意味着什么?
-d, --createdb role can create new databases
-E, --encrypted encrypt stored password
-i, --inherit role inherits privileges of roles it is a member of (default)
-l, --login role can login (default)
-P, --pwprompt assign a password to new role
-r, --createrole role can create new roles
-s, --superuser role will be superuser
现在,您应该通过输入以下命令离开postgres用户的bashShell环境:
exit
15.2.4. 验证新帐户
psql -l
应该返回类似如下的内容::
Name | Owner | Encoding | Collation | Ctype |
----------+----------+----------+------------+------------+
postgres | postgres | UTF8 | en_ZA.utf8 | en_ZA.utf8 |
template0 | postgres | UTF8 | en_ZA.utf8 | en_ZA.utf8 |
template1 | postgres | UTF8 | en_ZA.utf8 | en_ZA.utf8 |
(3 rows)
类型 Q 退场。
15.2.5. 创建一个数据库
这个 createdb
命令用于创建新数据库。它应该从bashShell提示符下运行:
createdb address -O qgis
您可以使用以下命令验证新数据库是否存在:
psql -l
它应该返回如下内容:
Name | Owner | Encoding | Collation | Ctype | Access privileges
----------+----------+----------+------------+------------+-----------------------
address | qgis | UTF8 | en_ZA.utf8 | en_ZA.utf8 |
postgres | postgres | UTF8 | en_ZA.utf8 | en_ZA.utf8 |
template0 | postgres | UTF8 | en_ZA.utf8 | en_ZA.utf8 | =c/postgres: postgres=CTc/postgres
template1 | postgres | UTF8 | en_ZA.utf8 | en_ZA.utf8 | =c/postgres: postgres=CTc/postgres
(4 rows)
类型 Q 退场。
15.2.6. 启动数据库Shell会话
您可以轻松地连接到数据库,如下所示:
psql address
要退出psql数据库Shell,请键入::
\q
有关使用Shell的帮助,请键入::
\?
有关使用SQL命令的帮助,请键入::
\help
要获取有关特定命令的帮助,请键入(例如):
\help create table
另请参阅 Psql cheat sheet 。
15.2.7. 在SQL中制作表格
让我们开始做一些桌子吧!我们将使用我们的ER图作为指导。首先,连接到地址db:
psql address
然后创建一个 streets
表:
create table streets (id serial not null primary key, name varchar(50));
serial 和 varchar 是 data types 。 serial 通知PostgreSQL启动一个整数序列(自动编号)以填充 id 每一项新记录都会自动执行。 varchar(50) 通知PostgreSQL创建一个长度为50个字符的字符字段。
您会注意到该命令以一个 ; -所有的SQL命令都应该这样终止。当您按下 Enter ,psql将报告类似以下内容:
NOTICE: CREATE TABLE will create implicit sequence "streets_id_seq"
for serial column "streets.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index
"streets_pkey" for table "streets"
CREATE TABLE
这意味着您的表已使用主键成功创建 streets_pkey 使用 streets.id 。
注意:如果按回车键时未输入 ; ,然后您将得到如下提示: address-# 。这是因为PG希望您输入更多内容。请输入 ; 来运行您的命令。
要查看您的表方案,您可以执行以下操作:
\d streets
它应该显示如下所示:
Table "public.streets"
Column | Type | Modifiers
--------+-----------------------+--------------------------------------
id | integer | not null default
| | nextval('streets_id_seq'::regclass)
name | character varying(50) |
Indexes:
"streets_pkey" PRIMARY KEY, btree (id)
要查看表内容,您可以执行以下操作:
select * from streets;
它应该显示如下所示:
id | name
---+------
(0 rows)
如您所见,我们的桌子目前是空的。
Try Yourself
使用上面显示的方法创建一个名为People的表:
添加电话号码、家庭住址、姓名等字段(这些不都是有效的名称:请更改它们以使其有效)。确保您为该表提供了一个数据类型与上面相同的ID列。
回答
创建正确的People表所需的SQL为:
create table people (id serial not null primary key,
name varchar(50),
house_no int not null,
street_id int not null,
phone_no varchar null );
表的模式(输入 \\d people
)如下所示::
Table "public.people"
Column | Type | Modifiers
-----------+-----------------------+-------------------------------------
id | integer | not null default
| | nextval('people_id_seq'::regclass)
name | character varying(50) |
house_no | integer | not null
street_id | integer | not null
phone_no | character varying |
Indexes:
"people_pkey" PRIMARY KEY, btree (id)
为便于说明,我们特意省略了fkey约束。
15.2.8. 在SQL中创建键
我们上面的解决方案的问题是,数据库不知道人和街道之间存在逻辑关系。要表达这种关系,我们必须定义一个指向Streets表的主键的外键。
有两种方法可以做到这一点:
在创建表之后添加密钥
在创建表时定义键
我们的表已经创建好了,所以让我们以第一种方式来完成:
alter table people
add constraint people_streets_fk foreign key (street_id) references streets(id);
这告诉我们 people 表,它的 street_id 字段必须与有效街道匹配 id 从 streets 桌子。
创建约束的更常见方法是在创建表时创建约束:
create table people (id serial not null primary key,
name varchar(50),
house_no int not null,
street_id int references streets(id) not null,
phone_no varchar null);
\d people
添加约束后,我们的表模式现在如下所示:
Table "public.people"
Column | Type | Modifiers
-----------+-----------------------+---------------------------------
id | integer | not null default
| | nextval('people_id_seq'::regclass)
name | character varying(50) |
house_no | integer | not null
street_id | integer | not null
phone_no | character varying |
Indexes:
"people_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"people_streets_fk" FOREIGN KEY (id) REFERENCES streets(id)
15.2.9. 在SQL中创建索引
我们想要对人名进行闪电般的快速搜索。为此,我们可以在People表的Name列上创建一个索引:
create index people_name_idx on people(name);
\d people
这将导致:
Table "public.people"
Column | Type | Modifiers
-----------+-----------------------+-----------------------------------
id | integer | not null default nextval
| | ('people_id_seq'::regclass)
name | character varying(50) |
house_no | integer | not null
street_id | integer | not null
phone_no | character varying |
Indexes:
"people_pkey" PRIMARY KEY, btree (id)
"people_name_idx" btree (name) <-- new index added!
Foreign-key constraints:
"people_streets_fk" FOREIGN KEY (id) REFERENCES streets(id)
15.2.10. 删除SQL中的表
如果您想要删除某个表,可以使用 drop 命令:
drop table streets;
在我们当前的示例中,上面的命令不起作用。为什么不行?
回答
DROP命令在这种情况下不起作用的原因是 people 表具有对 streets 桌子。这意味着删除(或删除) streets 表将离开 people 包含对不存在的引用的表 streets 数据。
这是有可能的‘强迫’ streets 要删除的表使用 CASCADE
命令,但这也会删除 people 以及任何其他与 streets 桌子。小心使用!
如果您使用相同的 drop table 上的命令 people 表,这将是成功的:
drop table people;
备注
如果您确实输入了该命令并删除了 people 表,现在是重建它的好时机,因为您将在下一个练习中使用它。
15.2.11. 浅谈pgAdmin III
我们将向您展示来自 psql 提示,因为这是学习数据库的一种非常有用的方式。然而,有更快、更容易的方法来完成我们向您展示的许多操作。安装pgAdmin III,您可以使用图形用户界面中的“指向并点击”操作来创建、删除、更改ETC表。
在Ubuntu下,可以这样安装:
sudo apt install pgadmin3
PgAdmin III将在另一个模块中详细介绍。
15.2.12. In Conclusion
现在您已经了解了如何完全从头开始创建一个全新的数据库。
15.2.13. What's Next?
接下来,您将学习如何使用DBMS添加新数据。