我试图为电话簿开发一个简单的数据库。这是我写的:将数据插入强归一化的数据库并保持完整性(Postgres)
CREATE TABLE phone
(
phone_id SERIAL PRIMARY KEY,
phone CHAR(15),
sub_id INT, -- subscriber id --
cat_id INT -- category id --
);
CREATE TABLE category
(
cat_id SERIAL PRIMARY KEY, -- category id --
cat_name CHAR(15) -- category name --
);
CREATE TABLE subscriber
(
sub_id SERIAL PRIMARY KEY,
name CHAR(20),
fname CHAR(20), -- first name --
lname CHAR(20), -- last name --
);
CREATE TABLE address
(
addr_id SERIAL PRIMARY KEY,
country CHAR(20),
city CHAR(20),
street CHAR(20),
house_num INT,
apartment_num INT
);
-- many-to-many relation --
CREATE TABLE sub_link
(
sub_id INT REFERENCES subscriber(sub_id),
addr_id INT
);
我创建了一个链接表许多一对多的关系,因为没有几个人能住在同一个地址和一个人可以生活在不同的时间不同的地点。
但我无法弄清楚如何在强标准化DB这样的添加数据和维护数据的完整性。
第一个改进是,我加入inique键上的地址表bacause此表不应该包含重复的数据:
CREATE TABLE address
(
addr_id SERIAL PRIMARY KEY,
country CHAR(20),
city CHAR(20),
street CHAR(20),
house_num INT,
apartment_num INT,
UNIQUE (country, city, street, house_num, apartment_num)
);
现在的问题是如何增加对一些人到数据库的新纪录。我想我应该用行动下一顺序:
插入记录
subscriber
表,因为sub_link
和phone
表必须使用新的用户的ID。将表中的记录插入
address
表中,因为在将记录添加到sub_link
之前必须存在addr_id
。将
subscriber
和address
的最后记录链接到sub_link
表中。但是在这一步我有一个新问题:如何在PostgreSQL中有效地从步骤1)和步骤2)获得sub_id
和addr_id
?然后,我需要插入一条记录到
phone
表。至于第3步,我不知道如何有效地从以前的查询中获得sub_id
。
我读了PostgreSQL里的WITH
块,但是我不知道如何在我的情况下使用它。
UPDATE 我喜欢做建议:
-- First record --
WITH t0 AS (
WITH t1 AS (
INSERT INTO subscriber
VALUES(DEFAULT, 'Twilight Sparkle', NULL, NULL)
RETURNING sub_id
),
t2 AS (
INSERT INTO address
VALUES(DEFAULT, 'Equestria', 'Ponyville', NULL, NULL, NULL)
RETURNING addr_id
)
INSERT INTO sub_link
VALUES((SELECT sub_id FROM t1), (SELECT addr_id FROM t2))
)
INSERT INTO phone
VALUES (DEFAULT, '000000', (SELECT sub_id FROM t1), 1);
但我有一个错误:包含一个数据修改语句必须是在顶层 线路2条:为T1 AS(INSERT INTO subscriber VALUES(DEFAULT,
Postgres允许在WITH块中执行两个排序插入吗?像这样:INSERT INTO sub_link VALUES((SELECT sub_id FROM t1),(SELECT addr_id FROM t2)),INSERT INTO phone VALUES(DEFAULT,“1111111”,(SELECT sub_id FROM t1),...' – memset
当然,只需将除最后一个INSERT之外的所有内容都放入它自己的WITH块中,每个WITH块都可以引用之前出现的别名,例如'... t3 AS(INSERT INTO sub_link VALUES((SELECT ... FROM t1),... ))INSERT INTO phone ...' – ASL
更新的原始帖子。查询变得非常复杂。使用嵌套的WITH'块,我得到一个错误'WITH子句包含一个数据修改语句必须在顶部' – memset