Таблица SQL, ссылающаяся на несколько внешних ключей, в то же время определяя порядок и гарантируя ссылочную целостность - PullRequest
2 голосов
/ 30 декабря 2010

Мой клиент указал, что ему нужно выполнить разные действия, когда выполняются определенные условия во внутренней логике. Каждый тип действия (на данный момент Command и WriteVariable) имеет индивидуальный набор конкретной информации и поэтому должен храниться в отдельной таблице. Пользователь должен иметь возможность определить порядок, в котором должны выполняться действия.

У меня есть следующие настройки для базы данных:

LogicTable
* OutputID
* Description

OutputTable <== a pure relational table
* OutputID
* LogicID
* ActionID <== this references one of the action tables (Command/WriteVariable)
* ActionTypeID
* Sequence

ActionTypeTable
* ActionTypeID
* Description

CommandTable
* CommandID  <== corresponds to ActionID in OutputTable
three columns with further command-specific information

WriteVariableTable
* WriteVariableID  <== corresponds to ActionID in OutputTable
four columns with further write-variable-specific information

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

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

Ответы [ 6 ]

1 голос
/ 30 декабря 2010
  • Каждое действие имеет простой тип (означает, что нет подэтапов).
  • "..when certain conditions in an internal logic are met" называется бизнес-событием .
  • Каждое бизнес-событие имеет определенный тип события .
  • Каждое бизнес-событие определенного событиятип приводит к набору действий .
  • Последовательность действий № указывает порядок действий в каждом наборе действий.

alt text

1 голос
/ 30 декабря 2010

Если клиент позволяет, вы можете добавить вычисляемые столбцы в таблицу OutputTable, например,

create table OutputTable (
  OutputID <datatype> <nullability>,
 LogicID <datatype> <nullability>,
 ActionID <datatype> <nullability>,
 ActionTypeID <datatype> <nullability>,
 Sequence <datatype> <nullability>,
  CommandActionID as CASE WHEN ActionTypeID = <Command Action> then ActionID END PERSISTED,
  WVActionID as CASE WHEN ActionTypeID = <Write Variable Action> then ActionID END PERSISTED,
    constraint FK_Output_CommandActions FOREIGN KEY (CommandActionID) references CommandTable (CommandID)
)

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

0 голосов
/ 30 декабря 2010

Короче говоря, да, я верю, что вы получили свои внешние ключи назад.Вот что я быстро придумал:

alt text

0 голосов
/ 30 декабря 2010

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

LogicTable
* OutputID
* Description

OutputTable <== a pure relational table
* OutputID
* LogicID
* ActionID
* ActionTypeID
* Sequence

ActionTypeTable
* ActionTypeID
* Description

Actions
* ActionID - primary key
* Sequence - not null
-- other columns as necessary to support the various
   actions, e.g. Command and WriteVariable

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

Actions
* ActionID - primary key
* Sequence - not null


ActionArguments
* ActionID - foreign key to Actions, part of primary key
* ArgumentName - not NULL, part of primary key
* ArgumentValue

Всего пара идей.

Делитесь и наслаждайтесь.

0 голосов
/ 30 декабря 2010

Я не вижу проблемы .... у вас уже есть OutputTable, который определяет последовательность, правильно? В таблице вывода также есть ActionID.

Итак, теперь каждая из ваших "дочерних" таблиц, таких как CommandTable и WriteVariableTable, должна просто ссылаться на OutputTable.ActionID. В SQL Server для этого вам нужно поставить UNIQUE INDEX на ActionID, а затем вы можете определить:

ALTER TABLE dbo.CommandTable
   ADD CONSTRAINT FK_CommandTable_OutputTable
   FOREIGN KEY(CommandID) REFERENCES dbo.CommandTable.ActionID

и

ALTER TABLE dbo.WriteVariableTable
   ADD CONSTRAINT FK_WriteVariableTable_OutputTable
   FOREIGN KEY(WriteVariableID) REFERENCES dbo.CommandTable.ActionID

и теперь у вас есть полностью проверенная ссылочная целостность - ваша последовательность определена в OutputTable, вы можете расширить ее, добавив дополнительные «дочерние» таблицы для других типов действий ......

0 голосов
/ 30 декабря 2010

Две возможности:

  1. Не можете ли вы добавить столбец OrderingId в таблицы Command и WriteVariable, которые вы используете для определения порядка действий, которые нужно выполнить? Вам нужно будет программно убедиться, что используемые порядковые номера правильно увеличиваются, так как БД не может обеспечить уникальность между таблицами, поэтому делайте это либо в коде приложения, либо в триггере / хранимой процедуре

  2. Иметь таблицу действий с orderingID (это может быть ваша таблица OutputTable)

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