Записи связаны с какой-либо таблицей? - PullRequest
6 голосов
/ 24 июля 2009

Привет, я немного борюсь с этим и могу использовать некоторые идеи ...

Скажем, в моей базе данных есть следующие таблицы;Клиенты Поставщики SalesInvoices Покупки Invoices Валюты

и т. Д. И т. Д.

Я хотел бы иметь возможность добавить запись «Примечания» к ЛЮБОМУ типу записи

Таблице примечаний понравилось бы это

NoteID        Int (PK)
NoteFK        Int
NoteFKType    Varchar(3)
NoteText      varchar(100)
NoteDate      Datetime

Где NoteFK - это PK клиента или поставщика и т. Д., А NoteFKType говорит, к какому типу записи относится заметка

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

Так как бы вы разработали вышеперечисленное? Примечание FK должно быть в любой из приведенных выше таблиц

Приветствия, Даниэль

Ответы [ 8 ]

3 голосов
/ 24 июля 2009

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

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

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

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

2 голосов
/ 24 июля 2009

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

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

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

1 голос
/ 24 июля 2009

Вы можете получить ссылочную целостность FK за счет наличия одного столбца в таблице заметок для каждой другой таблицы.

create table Notes (
    id int PRIMARY KEY,
    note varchar (whatever),
    customer_id int NULL REFERENCES Customer (id),
    product_id int NULL REFERENCES Product (id)
)

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

Или, возможно, нет, может быть, вы захотите заметку, чтобы иметь возможность ассоциировать ее как с клиентом, так и с продуктом. До вас.

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

1 голос
/ 24 июля 2009

Я согласен с Майклом Маклоски, в некоторой степени.

Вопрос в моей голове: какова техническая стоимость наличия нескольких таблиц заметок?

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

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


Чтобы ответить на ваш вопрос ...

Опция, которую я бы использовал, - это ограничение проверки с использованием определяемой пользователем функции для проверки значений. Это работает в M $ SQL Server ...

CREATE TABLE Test_Table_1 (id INT IDENTITY(1,1), val INT)
GO
CREATE TABLE Test_Table_2 (id INT IDENTITY(1,1), val INT)
GO
CREATE TABLE Test_Table_3 (fk_id INT, table_name VARCHAR(64))
GO

CREATE FUNCTION id_exists (@id INT, @table_name VARCHAR(64))
RETURNS INT
AS
BEGIN
    IF (@table_name = 'Test_Table_1')
        IF EXISTS(SELECT * FROM Test_Table_1 WHERE id = @id)
            RETURN 1
    ELSE
    IF (@table_name = 'Test_Table_2')
        IF EXISTS(SELECT * FROM Test_Table_2 WHERE id = @id)
            RETURN 1

    RETURN 0
END
GO

ALTER TABLE Test_Table_3 WITH CHECK ADD CONSTRAINT
    CK_Test_Table_3 CHECK ((dbo.id_exists(fk_id,table_name)=(1)))
GO
ALTER TABLE [dbo].[Test_Table_3] CHECK CONSTRAINT [CK_Test_Table_3]
GO

INSERT INTO Test_Table_1 SELECT 1
GO
INSERT INTO Test_Table_1 SELECT 2
GO
INSERT INTO Test_Table_1 SELECT 3
GO
INSERT INTO Test_Table_2 SELECT 1
GO
INSERT INTO Test_Table_2 SELECT 2
GO
INSERT INTO Test_Table_3 SELECT 3, 'Test_Table_1'
GO
INSERT INTO Test_Table_3 SELECT 3, 'Test_Table_2'
GO

В этом примере завершающий оператор вставки потерпит неудачу.

1 голос
/ 24 июля 2009

Я бы дважды подумал, прежде чем делать то, что вы предлагаете. В краткосрочной перспективе это может показаться простым и элегантным, но если вы действительно заинтересованы в целостности и производительности данных, то лучше всего использовать отдельные таблицы заметок для каждой родительской таблицы. На протяжении многих лет я подходил к этой проблеме, используя решения, найденные в других ответах (триггеры, GUID и т. Д.). Я пришел к выводу, что сложность и потеря производительности того не стоят. Имея отдельные таблицы заметок для каждой родительской таблицы с соответствующими ограничениями внешнего ключа, поиск и объединение будут простыми и быстрыми. При объединении связанных элементов в одну таблицу синтаксис объединения становится безобразным, и ваша таблица заметок будет расти огромной и медленной.

0 голосов
/ 24 июля 2009

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

0 голосов
/ 24 июля 2009

Вы можете добавить поле GUID в таблицы «Клиенты», «Поставщики» и т. Д. Затем в таблице «Примечания» измените внешний ключ, указав этот GUID.

Это не поможет обеспечить целостность данных. Но это делает отношения M-to-N легко возможными для любого количества таблиц и избавляет вас от необходимости определять столбец NoteFKType в таблице Notes.

0 голосов
/ 24 июля 2009

Почему вы не делаете это наоборот и не имеете внешнего ключа в других таблицах (Клиент, Поставщик и т. Д.) Для NotesID. Таким образом, у вас есть однозначное сопоставление.

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