Может ли побитовая математика использоваться для отношений "один ко многим" в SQL?

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

Ответ 1

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

Тем не менее, многие базы данных предлагают поддержку для этого, как правило, через "бит" типа данных. У Mysql есть еще более сильная поддержка с типом данных "set".

Основная проблема заключается в том, что вы ничего не знаете о элементах в наборе - что такое полное имя, когда оно было добавлено в базу данных и т.д. (Enums обходят часть проблемы с именами.) Кроме того, размер набора ограничен. У вас может быть пример, где все ограничено. Однако пример Мэтта скорее подчеркивает проблему здесь. У вас может быть список посещенных континентов. Однако, когда вы переключаетесь на посещаемые страны, подход, безусловно, совершенно другой, потому что число стран больше не вписывается ни в одно "слово". Хотели бы вы, чтобы ваша система относилась к континентам совсем иначе, чем страны в этом отношении? Вы хотите, чтобы ваши проектные решения были ограничены лимитом 32 или 64 бита в компьютерном слове?

И, наконец, вы, похоже, рассматриваете распространение таблиц как проблему. Распространение таблиц на самом деле является решением. Все данные об объектах хранятся в таблицах, а не распространяются через систему. Вы можете хранить информацию о экземплярах объекта, например, когда экземпляр был создан, как он мог измениться с течением времени и т.д. Сущность для "континентов", вероятно, будет использоваться всякий раз, когда кто-то хочет континент.

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

Ответ 2

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

Скажем, у нас есть стол Person и wed, чтобы знать, сколько континентов посетил человек. Wed начните с присвоения каждому континенту "ортогонального" значения бит. В С#, перечисление является хорошим выбором для этого:

[Flags]
public enum JobAdvertisingRegion
{
    NorthAmerica = 1,              // or 1 << 0
    SouthAmerica = 2,              // 1 << 1
    Europe = 4,                    // 1 << 2
    Asia = 8,                      // 1 << 3
    Africa = = 16,                 // 1 << 4
    Australia = 32,                // 1 << 5
    Anarctica = 64                 // 1 << 6
}

В таблице "Люди" может быть просто столбец "Контекст". Чтобы указать, что человек посетил Европу и Азию:

UPDATE Persons SET Continents = (4 + 8) WHERE Id = whatever

Чтобы найти людей, которые посетили Антарктиду, мы используем поразрядную математику:

SELECT * FROM Persons WHERE Continents & 64 = 64

Поиск людей, которые посетили как Африку, так и Азию:

SELECT * FROM Persons WHERE Continents & (16 + 8) = (16 + 8)

Поиск лиц, которые посетили Австралию или Южную Америку:

SELECT * FROM Persons WHERE Continents & (32 + 2) != 0

Один недостаток заключается в том, что, хотя целочисленные столбцы индексируются в SQL, их битовые компоненты не являются. Некоторые оптимизации, чтобы обойти это, для вышеуказанных запросов:

SELECT * FROM Persons WHERE Continents & 64 = 64 AND Continents >= 64

SELECT * FROM Persons WHERE Continents & (16 + 8) = (16 + 8) AND Continents >= (16 + 8)

SELECT * FROM Persons WHERE Continents & (32 + 2) != 0 AND Continents >= 2

Ответ 3

Хорошо, я пойду против (в настоящее время) популярного мнения здесь, просто заявив несколько фактов

  • SQL и реляционная модель не соответствуют не.
  • Реляционная модель (теория) работает с реляционными переменными, так называемыми relvars.
  • Базы данных SQL используют таблицы.
  • Таблицы и реверты не совпадают, но могут быть - для всех практических целей.
  • Чтобы использовать теорию реляционного моделирования, таблицы должны представлять relvars.
  • Для таблицы, представляющей реляционную переменную, должно быть верно следующее:

    • Строки не имеют порядка
    • Столбцы не имеют порядка
    • Нет повторяющихся строк
    • Каждое пересечение столбцов и строк имеет только одно значение типа, определенного столбцом
    • Нет специальных скрытых столбцов (идентификаторы строк, идентификаторы объектов...)

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

Технически ваш пост (вопрос) имеет два ответа.

  • Да, к названию сообщения.
  • Нет, к телу сообщения.