Идентификаторы в ромбовидной связи между таблицами

StackOverflow https://stackoverflow.com/questions/357328

Вопрос

У меня есть четыре таблицы (A,B,C,D), где A является родительским элементом отношений «один ко многим» с B и C.C и D являются родительскими элементами связи один-ко-многим с таблицей D.Концептуально первичными ключами этих таблиц могут быть:

  • А:Помогать
  • Б:Помощь, bnum (с внешним ключом к A)
  • С:Помощь, cnum (с внешним ключом к A)
  • Д:Aid, bnum, cnum (с внешними ключами для B и C)

Где столбцы «num» автоматически увеличиваются на основе каждого родительского идентификатора в отношениях, а не на каждой записи.Я использовал этот подход в предыдущем приложении, и это не было проблемой, поскольку создание записей B и C выполнялось последовательным процессом путем создания нового значения «num» с помощью запроса «select max()».Я никогда не был по-настоящему удовлетворен этим подходом, но он выполнил свою работу.

В конкретном случае, над которым я сейчас работаю, записи в таблицах A и B вводятся пользователями, поэтому автоматическое создание идентификаторов не является проблемой.В случае таблиц C и D записи в этих таблицах генерируются несколькими параллельными пакетными процессами, поэтому их идентификаторы необходимо каким-то образом сгенерировать.Предыдущий метод, который я перечислил, не будет работать в условиях гонки.

Обратите внимание, что это касается базы данных Oracle, поэтому я буду использовать последовательности, а не столбцы с автоматическим приращением.

Учитывая вышеизложенные ограничения, как бы вы разработали таблицы для представления A, B, C и D, чтобы отношения между сущностями были правильно реализованы, И коду приложения не требовалось бы генерировать какие-либо идентификаторы?

Это было полезно?

Решение

Если я правильно понимаю, у вас было решение, в котором вы могли

Table A
-------
100
101
102

Table B
-------
100 1
100 2
101 1

Table C
-------
100 1
100 2
101 1


Table D
-------
100 1 1
100 2 1
100 1 2
101 1 1

и т. д.

Итак, имеет ли значение, малы ли значения «num» и расположены ли они в последовательности без пробелов?Если нет, то просто используйте последовательности и для них.Таким образом, вы можете получить

Table B
-------
100 29125
100 29138
101 29130

Table D
-------
100 29125 401907
100 29138 404911
101 29130 803888

Я бы использовал отдельные последовательности для bnum и cnum.При выборе вы можете (при желании) использовать что-то вроде

SELECT AID, 
      RANK(BNUM) OVER (PARTITION BY AID ORDER BY BNUM) bnum_seq,
      RANK(CNUM) OVER (PARTITION BY AID ORDER BY CNUM) cnum_seq

Другие советы

Последовательности или автонумерации всегда должны генерироваться системой базы данных, а не приложением.Для MSSQL это можно сделать с помощью хранимой процедуры и возврата «select @@identity» из хранимой процедуры, чтобы передать приложению идентификатор вставленной строки.

Последовательности отлично подходят для первичных ключей, но есть лагеря, которые поклоняются богу «естественных ключей».

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

Лично я бы создал последовательности первичных ключей в каждой таблице и позволил бы использовать внешние ключи, которые не являются частью первичного ключа.Вы определите свои таблицы по основным объектам (например, сотрудник, товар, магазин), а затем отношения между ними будут состоять из комбинаций. Таким образом, у сотрудника в магазине будет таблица «storeemployee», а первичный ключ будет empid. , storeid без определенной последовательности.Обычно я думаю об этом с точки зрения объектов (которые всегда имеют последовательности для первичных ключей) и отношений между объектами (с использованием идентификаторов других таблиц в качестве комбинированных первичных ключей).

Надеюсь, это поможет!

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top