Наследование таблиц SQL, вызывающее дублирование записей в базовой таблице, даже если установлено ограничение первичного ключа - PullRequest
8 голосов
/ 12 августа 2011

У меня есть проблема, где, скажем, у меня есть таблица людей, которая наследуется таблицей ученика и таблицей учителя. если я сделаю учащегося INSERT INTO и учителя INSERT INTO и укажу первичный ключ таблицы людей (P_Id), например

INSERT INTO student(P_Id, LastName, FirstName, StudentNumber)
VALUES (1, 'Jones', 'Casey', 'SID0001');

INSERT INTO teacher(P_Id, LastName, FirstName, FacultyNumber)
VALUES (1, 'Jones', 'Casey', 'JONES0001');

Я получаю две дубликаты записей в моей таблице сотрудников (P_Id - мой первичный ключ в таблице сотрудников). Похоже, что вложенные таблицы выполняют вставки в таблицу сотрудников без учета ограничений для этой таблицы. не должно ли ограничение первичного ключа на таблицу сотрудников предотвратить создание дублирующихся записей?

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

После этого возникнет ли проблема с изменением Фамилии, например, в таблице учеников, и отражением этих изменений в таблице учителя?

Вот операторы create, приведенные выше операторы Insert, которые служат только для примера, который, как я понимаю, не будет работать с этими таблицами, которые создаются:

CREATE TABLE people
(
people_id integer NOT NULL,
last_name character varying NOT NULL,
first_name character varying NOT NULL,
middle_name character varying,
gender character varying NOT NULL,
date_of_birth date,
ssn character varying,
pref_language character varying,
CONSTRAINT people_pkey PRIMARY KEY (people_id)
)

CREATE TABLE student
(
-- Inherited from table people:  people_id integer NOT NULL,
-- Inherited from table people:  last_name character varying NOT NULL,
-- Inherited from table people:  first_name character varying NOT NULL,
-- Inherited from table people:  middle_name character varying,
-- Inherited from table people:  gender character varying NOT NULL,
-- Inherited from table people:  date_of_birth date,
-- Inherited from table people:  ssn character varying,
-- Inherited from table people:  pref_language character varying,
student_id integer NOT NULL,
race character varying(80),
ethnicity character varying(80),
employer character varying(80),
school character varying(80),
pref_location character varying(80),
CONSTRAINT student_pkey PRIMARY KEY (student_id)
)
INHERITS (people)

CREATE TABLE teacher
(
-- Inherited from table people:  people_id integer NOT NULL,
-- Inherited from table people:  last_name character varying NOT NULL,
-- Inherited from table people:  first_name character varying NOT NULL,
-- Inherited from table people:  middle_name character varying,
-- Inherited from table people:  gender character varying NOT NULL,
-- Inherited from table people:  date_of_birth date,
-- Inherited from table people:  ssn character varying,
-- Inherited from table people:  pref_language character varying,
teacher_id integer NOT NULL,
user_name character varying NOT NULL,
"password" character varying NOT NULL,
title character varying,
CONSTRAINT teacher_pkey PRIMARY KEY (teacher_id)
)
INHERITS (people)

Ответы [ 4 ]

5 голосов
/ 04 декабря 2013

Правила ограничений не наследуются, поэтому вам нужно определить ограничение в каждой таблице. Например:

CREATE TABLE people (
    id int ,
    name varchar(20),
    CONSTRAINT people_pkey PRIMARY KEY (id)
);

CREATE TABLE individual (
    cpf varchar(11),
    CONSTRAINT individual_pkey PRIMARY KEY (id)
) INHERITS (people);


CREATE TABLE legal_entity (
    cnpj varchar(14),
    CONSTRAINT legal_entity_pkey PRIMARY KEY (id)
) INHERITS (people);

Увидимся.

5 голосов
/ 13 августа 2011

Я думаю, что это поведение разработано.Из документов PostgreSQL .,.

INSERT всегда вставляется точно в указанную таблицу.

И чуть дальше вниз по странице.,.

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

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

Из раздела «Предостережения».,.

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

Тот же раздел.

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

1 голос
/ 12 августа 2011

Ваш первичный ключевой набор полей - Identity? ограничить уникальность?

0 голосов
/ 12 августа 2011

Вы никогда не вставляете в дочерние таблицы первыми! Таблица person - это первая таблица, в которую вы должны вставить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...