Уникальная константа и нормализация данных в Oracle - PullRequest
0 голосов
/ 10 января 2020

У меня есть следующие таблицы (для краткости я удалил ограничения и несвязанные столбцы) :

CREATE TABLE user (
    user_id INT,
    user_name VARCHAR
);
CREATE TABLE book (
    book_id INT
);
CREATE TABLE book_author (
    book_author_id INT,
    book_id INT,
    author_name VARCHAR
);
CREATE TABLE book_author_user_match (
    book_author_id INT,
    user_id INT
)

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

Вот часть, на которой я застрял. Достаточно просто добавить столбец book_id и уникальное ограничение на (book_id, user_id). Однако я не хочу добавлять столбец book_id в таблицу, поскольку таблицу book_author можно объединить в столбец book_author_id, чтобы найти book_id. Другими словами, наличие в таблице столбцов book_author_id и book_id приводит к нормализации данных.

Я вижу только следующие варианты:

  1. добавить book_id и просто жить с ненормализованными данными
  2. не имеют уникального ограничения и вместо этого обеспечивают один user_id на книгу на уровне кода

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

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

Ответы [ 3 ]

0 голосов
/ 10 января 2020

У вас есть пользователи, которые могут быть авторами. Может быть, один пользователь даже представляет двух или более авторов (т.е. пишет под разными псевдонимами). Отношение 1: n (идентификатор пользователя в таблице авторов).

Далее идут книги. Книга может быть написана несколькими авторами, а автор может написать несколько книг. Отношение m: n (для которого требуется таблица мостов).

Это модель данных, которую я вижу:

CREATE TABLE user (
    user_id      INT      NOT NULL,
    user_name    VARCHAR  NOT NULL,
    PRIMARY KEY (user_id)
);

CREATE TABLE author (
    author_id    INT      NOT NULL,
    author_name  VARCHAR  NOT NULL,
    user_id      INT      NULL,
    PRIMARY KEY (author_id),
    FOREIGN KEY (user_id) REFERENCES user(user_id)
);

CREATE TABLE book (
    book_id      INT      NOT NULL,
    title        VARCHAR  NOT NULL
);

CREATE TABLE book_author (
    book_id      INT      NOT NULL,
    author_id    INT      NOT NULL,
    PRIMARY KEY (book_id, author_id),
    FOREIGN KEY (book_id) REFERENCES book(book_id),
    FOREIGN KEY (author_id) REFERENCES author(author_id)
);
0 голосов
/ 10 января 2020

Вы получаете книги из другой системы. Список может быть следующим:

  • Хорошая книга, автор Джон Смит
  • Великая книга, авторы Джон Смит, Джейн Смит
  • Лучшая книга, автор Дж. Смит

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

В комментарии к моему другому ответу вы говорите, что не хотите, чтобы один и тот же человек упоминался в качестве автора книги. дважды. В этом сценарии г-н X не может использовать оба псевдонима Джон Смит и Джейн Смит и написать только «Великую книгу» (или вам понадобится другой псевдоним автора «Джейн и Джон Смит» для этого автора: -)

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

CREATE TABLE user (
    user_id      INT      NOT NULL,
    user_name    VARCHAR  NOT NULL,
    PRIMARY KEY (user_id)
);

CREATE TABLE book (
    book_id      INT      NOT NULL,
    title        VARCHAR  NOT NULL
);

CREATE TABLE book_author (
    book_id      INT      NOT NULL,
    author_name  VARCHAR  NOT NULL,
    user_id      INT      NULL,
    PRIMARY KEY (book_id, author_name),
    UNIQUE KEY (book_id, user_id),
    FOREIGN KEY (book_id) REFERENCES book(book_id),
    FOREIGN KEY (user_id) REFERENCES user(user_id)
);
0 голосов
/ 10 января 2020

Вам нужно хранить авторов в отдельной таблице

CREATE TABLE user (
    user_id INT,
    user_name VARCHAR
);
CREATE TABLE book (
    book_id INT
);
CREATE TABLE author (
    author_id INT,
    author_name VARCHAR
);    
CREATE TABLE book_author (
    book_author_id INT,
    book_id INT,
    author_id INT
);
CREATE TABLE book_author_user_match (
    book_author_id INT,
    user_id INT
)

И установить user_id и book_author_id либо как первичный, либо как уникальный ключ

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