Распространение первичного ключа на дочерние таблицы

Я хочу распространить значение столбца первичного ключа из родительской таблицы в конкретную дочернюю таблицу при вставке новой строки.

Для пояснения я создал следующие таблицы:

Create TABLE Material(
MatID serial PRIMARY KEY,
materialname TEXT
);

Create TABLE RealMaterial(
MatID INT REFERENCES Material(MatID),
attributereal TEXT,
PRIMARY KEY(MatID)
);

Create TABLE VirtualMaterial(
MatID INT REFERENCES Material(MatID),
attributevirt TEXT,
PRIMARY KEY(MatID)
);

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

Должен ли я использовать триггер для своих целей?

2 ответа

Решение

Из ваших комментариев кажется, что вы на самом деле не заинтересованы в "автоматической вставке", а скорее в "автоматическом обеспечении" присутствия 1 и исключительности 2 детей.

Поскольку PostgreSQL поддерживает отложенные ограничения, вы можете сделать это декларативно, как это.

Однако это требует "уродливости" вашей модели и, как правило, увеличивает сложность, поэтому применение таких ограничений на уровне приложений часто считается меньшим злом. Вы можете спрятать такую ​​логику за API, чтобы исключить возможность "мошеннических" клиентов обойти его.


1 Для данной родительской строки должна быть дочерняя строка. Другими словами, родительский класс сам по себе не может быть создан - он абстрактный.

2 Для данной родительской строки не может быть более одной дочерней строки.

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

IF (TG_OP = 'INSERT') THEN
    IF NEW.Parameter = 'REAL' THEN
        INSERT INTO RealMaterial (MatID) VALUES (NEW.MatID);
    ELSE
        INSERT INTO VirtualMaterial (MatID) VALUES (NEW.MatID);
    END IF;
END IF;

Я понятия не имею о связи (если есть) между Material.Parameter и Parameter2 и Parameter3. Предполагая, что Material.Parameter контролирует, является ли материал реальным или виртуальным, вам нужно будет обрабатывать как INSERTS, так и UPDATES и иметь возможность перемещать материал из "RealMaterial" в "VirtualMaterial" и наоборот. Вероятно, вы можете обрабатывать удаления с помощью внешнего ключа (каскад).

Два незапрошенных совета:

  1. При публикации всегда дайте как можно больше (соответствующей) информации. Это приведет к лучшим ответам. Здесь объяснение отношений поможет. Кроме того, вы всегда должны включать информацию о том, какую версию PostgreSQL вы используете.
  2. Судя по моему опыту, кажется, что вам нужны не разные столы, а один стол. Я настоятельно рекомендовал бы реализовать это в виде единой таблицы.
Другие вопросы по тегам