Определите отношения один-ко-многим с SQL - PullRequest
4 голосов
/ 10 декабря 2011

Я ищу способ установить отношение один ко многим между двумя таблицами. Структуры таблиц описаны ниже, но я попытался исключить все, что не имеет отношения к проблеме.

Таблица objects имеет 1 столбец с именем uuid.

Таблица contents имеет 3 столбца, которые называются content, object_uuid и timestamp.

Основная идея - вставить строку в objects и получить новый uuid из базы данных. Этот uuid затем используется для хранения каждой строки в contents, чтобы связать содержимое с объектами.

Теперь я пытаюсь использовать базу данных для обеспечения этого:

  • Каждая строка в contents ссылается на строку в objects (внешний ключ должен делать)
  • Ни одна строка в objects не существует без хотя бы row в contents

Эти ограничения должны применяться при фиксации транзакций.

Обычные триггеры не могут помочь, вероятно, потому что, когда записывается строка в таблице objects, в contents еще не может быть строки. У Postgres есть так называемый constraint triggers, который можно отложить до конца транзакции. Можно было бы использовать их, но они кажутся некой внутренней конструкцией, не предназначенной для повседневного использования.

Идеи или решения должны быть стандартными SQL (предпочтительно) или работать с Postgres (версия не имеет значения). Спасибо за любой вклад.

Ответы [ 2 ]

2 голосов
/ 10 декабря 2011

Ваша основная проблема заключается в том, что помимо ограничений внешнего ключа; никакое ограничение не может ссылаться на другую таблицу.

Лучше всего немного денормализовать это и иметь столбец на object, содержащий количество contents, которые ссылаются на него. Вы можете создать триггер, чтобы поддерживать это в актуальном состоянии.

contents_count INTEGER NOT NULL DEFAULT 0

Это не будет столь же неразрушимо, если вы не наденете некоторую безопасность пользователя, который может обновить этот столбец. Но если вы будете поддерживать его в актуальном состоянии с помощью триггера, и все, чего вы хотите избежать - это случайного повреждения, этого должно быть достаточно.

РЕДАКТИРОВАТЬ : Согласно комментарию, ограничения CHECK не являются отложенными. Это решение приведет к ошибке, если все содержимое будет удалено, даже если планируется добавить еще в той же транзакции.

0 голосов
/ 10 декабря 2011

Может быть, вы хотите нормализовать немного больше. Вам нужна третья таблица, которая ссылается на элементы других таблиц. Таблица objects должна иметь свой собственный uuid, а таблица contents должна также иметь свой собственный uuid и не иметь ссылки на таблицу objects. Третья таблица должна содержать только ссылки на две другие таблицы, но первичным ключом является комбинация обеих ссылок. так, например, у вас есть uuid таблицы objects и вы хотите получить все содержимое этого uuid, при условии, что третья таблица имеет столбцы object_uuid и content_uuid, а содержимое таблицы имеет собственный последовательный столбец с именем uuid, ваш запрос должен быть таким:

SELECT * FROM thirdtable,contents 
   WHERE thirdtable.content_uuid = contents.uuid AND thirdtable.object_uuid=34;

Затем вы можете использовать триггер включения для каждой таблицы

CREATE TRIGGER my_insert_trigger AFTER INSERT OR UPDATE ON contents
   FOR EACH ROW EXECUTE PROCEDURE my_check_function();

и затем в функции my_check_function () удалите все строки в objects, которых нет в третьей таблице. Кто-то еще ответил первым, когда я отвечал, если вам, ребята, нравится мое решение, я могу помочь вам сделать функцию my_check_function ().

...