Связывание таблиц в Postgresql
Помогите разобраться в связывании таблиц в Postgresql (один ко многим). Есть несколько помещений, в каждом из которых установлен электросчетчик. Необходимо таблицу с помещениями связать с таблицей, где находятся переданные показания всех счетчиков (передаются ежемесячно на протяжении длительного времени).
Связывыю внешним ключом meter из таблицы places с полем meter_number в таблице meters.
а) таблица с помещениями:
CREATE TABLE places (
id integer PRIMARY KEY,
name text,
meter integer NOT NULL
);
б) таблица с показаниями счетчиков:
CREATE TABLE meters (
id integer PRIMARY KEY,
meter_number integer NOT NULL,
data integer NOT NULL,
UNIQUE (id, meter_number)
);
Внешний ключ будет ссылаться на поле meter_number, но это поле не уникально (т.к. в таблице meters показания по каждому счётчику за большой интервал времени), поэтому делаю уникальность для группы столбцов (id и meter_number).
в) делаю связь между таблицами:
ALTER TABLE places
ADD CONSTRAINT meters FOREIGN KEY (meter)
REFERENCES meters (meter_number) ON UPDATE CASCADE ON DELETE CASCADE;
Получаю ошибку:
«ERROR: there is no unique constraint matching given keys for referenced table "meters" SQL-состояние: 42830»
Подскажите, что делаю не так? Может вообще нужно было делать таблицу с показаниями счётчиков в другом виде (один счётчик – одна таблица)? Но вроде и так должно работать, просто у меня пока не получается.
Ответы (1 шт):
Во-первых, нелогично, что помещение ссылается на счетчик, должно быть наоборот. Ведь в принципе, в одном помещении может быть несколько счетчиков, а вот один счетчик не может находится в нескольких помещениях. Сейчас у вас структура позволяет такое.
Во-вторых, нужно разделить счетчики и показания счетчиков в отдельные таблицы.
Итого имеем:
CREATE TABLE place (
id integer PRIMARY KEY,
name text
);
CREATE TABLE meter (
id integer PRIMARY KEY,
place_id integer NOT NULL REFERENCES place (id)
);
CREATE TABLE meter_data (
id integer PRIMARY KEY,
meter_id integer NOT NULL REFERENCES meter(id),
data integer NOT NULL
);