私は電話帳用の簡単なデータベースを開発しようとしています。これは私が書いたものである:強く正規化されたDBにデータを挿入して整合性を維持する(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にデータを追加する方法を理解することはできず、データの整合性を維持しています。
第1の改良は、私は、このテーブルbacauseアドレステーブルの上にiniqueキーを追加しましたが、重複データを含むべきではないということでした。
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)
);
さて問題は、DBにいくつかの人についての新しいレコードを追加する方法です。 sub_link
とphone
テーブルが新たな加入者のIDを使用しなければならないので、subscriber
テーブルにレコードを挿入し
:私は、私はアクションの次の順序を使用すべきだと思います。
sub_link
にレコードを追加する前にaddr_id
が存在する必要があるため、address
テーブルにレコードを挿入してください。subscriber
とaddress
の最後のレコードをsub_link
テーブルにリンクします。しかし、このステップで私は新しい問題を抱えています:PostgreSQLのステップ1)と2)のsub_id
とaddr_id
をどうすれば効果的に入手できますか?次に、
phone
テーブルにレコードを挿入する必要があります。 3)のステップでは、以前のクエリからsub_id
を効果的に取得する方法はわかりません。
私はPostgresの約WITH
ブロックを読んで、私は私の場合はそれを使用する方法を見つけ出すことはできません。
-- 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);
をしかし、私はエラーがあります:T1 WITH:データ変更文を含む句WITH がトップレベル LINE 2でなければならないが提案のように、私がやった
UPDATE AS(INSERT INTO加入者のVALUES(DEFAULT、
postgresはWITHブロックに2つのシーケンシング挿入を実行できますか?これは次のようなものです: 'INSERT INTO sub_link VALUES(SELECT sub_id FROM t1)、(SELECT addr_id FROM t2))、INSERT INTO電話機の値(DEFAULT、" 1111111 "、(SELECT sub_id FROM t1)、... – memset
確かに、たとえば、最後のINSERTを除くすべてのINSERTをそれ自身のWITHブロックに入れてください。それぞれのWITHブロックは、それ以前の別名を参照できます。 ))INSERT INTO phone ... ' – ASL
元の投稿が更新されました。クエリが非常に複雑になりました。入れ子になった 'WITH'ブロックを使用して、'データ変更文を含むWITH節が先頭になければならない'というエラーが発生しました。 – memset