Правила отношений между различными SQL таблицами - PullRequest
2 голосов
/ 05 марта 2020

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

Это упрощенная версия, чтобы проиллюстрировать мою проблему:

Субъекты

  • Сторона
  • Контракт
  • Ущерб

Отношения

  • Договор всегда связан со стороной (довольно легко)
  • Ущерб должен быть связан со стороной, но при желании может быть связан с договором

Итак, последнее отношение - проблема здесь. Так как наша конечная точка - это API, и люди могут потенциально отправить guid Стороны А и guid Договора Y, который связан со Стороной B.

, которая затем ущерб принадлежит либо Стороне А, либо Б, и это не должно быть возможным. Можно добавить проверку при добавлении ущерба, чтобы убедиться, что Сторона == Контракт. Партия, но мне кажется, что я обманываю базу данных отношений.

Я не уверен, как эта проблема называется и как ее решить.

Ответы [ 2 ]

1 голос
/ 05 марта 2020

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

Решение, показанное ниже, будет работать с любой реляционной базой данных без дополнительного кода:

create table party (
  id int primary key not null
);

create table contract (
  party_id int not null,
  contract_no int not null,
  primary key (party_id, contract_no),
  constraint fk1 foreign key (party_id) references party (id)
);

create table damage (
  id primary key not null,
  party_id int not null, -- not nullable
  contract_no int,       -- nullable
  constraint fk2 foreign key (party_id) references party (id),
  constraint fk3 foreign key (party_id, contract_no) 
         references contract (party_id, contract_no)
);

Примечание: Стандарт SQL определяет три варианта соответствия для частично нулевых FK (нет, частично, полностью), но каждая база данных позволяет использовать любой из них.

0 голосов
/ 05 марта 2020

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

CREATE FUNCTION dbo.IdMismatches()
RETURNS int
AS BEGIN RETURN (
    SELECT COUNT(*)
    FROM Damage d
    JOIN Contract c ON d.ContractId = c.Id
    WHERE d.PartyId != c.PartyId
) END
go
ALTER TABLE Damage ADD CONSTRAINT chkMismatches CHECK (dbo.IdMismatches() = 0);

. ищу, но я думаю, что нет никакого способа избежать необходимости использовать подобные проверки. Таким образом, по крайней мере, SQL Сервер применяет ограничение.

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

...