我試圖爲電話簿開發一個簡單的數據庫。這是我寫的:將數據插入強歸一化的數據庫並保持完整性(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