Я пытаюсь создать простую базу данных для телефонной книги. Это то, что я писал:Вставьте данные в строго нормированную БД и поддерживайте целостность (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
);
Я создал таблицу ссылок на многие ко многим отношения, потому что немногие люди могут жить по тому же адресу и один человек может жить в разных местах в разное время.
Но я не могу понять, как добавить данные в сильно нормированную БД, как это, и поддерживать целостность данных.
Первое улучшение был то, что я добавил 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
таблицы должны использовать идентификатор нового абонента.Впишите запись в таблицу
address
, так какдолжен существовать до добавления записи вsub_link
.Ссылка последние записи из
subscriber
иaddress
вsub_link
таблица. Но на этом этапе у меня возникла новая проблема: как я могу получитьsub_id
иaddr_id
с шагов 1) и 2) в PostgreSQL?Затем мне нужно вставить запись в таблицу
phone
. Как и на этапе 3), я не знаю, как эффективно получитьsub_id
из предыдущих запросов.
Я прочитал о WITH
блок в Postgres, но я не могу понять, как использовать его в моем случае.
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 абонент 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