DB Design для хранения пользовательских полей для таблицы - PullRequest
2 голосов
/ 27 мая 2010

этот вопрос возник на основе ответов, которые я получил на вопрос Странная проблема с функцией TO_NUMBER в Oracle

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

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

например. Я излагаю гипотетический сценарий ниже

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

Пользователь создал продукт для ноутбука, скажем, lap1 с атрибутами String, String, numeric, numeric, String

Второй пользователь создал ноутбук lap2 с атрибутами String, numeric, String, String, numeric

В настоящее время данные в нашем дизайне сохраняются следующим образом

Laptop Table
Id Name field1  field2 field3  field4 field5
1  lap1 lappy   lappy  12      13     lappy
2  lap2 lappy2  13     lappy2  lapp2  12

Этот пример моделирует наше требование и наш дизайн

Теперь, если кто-то просматривает записи для таблицы lap2 и выполняет сравнение с field2, нам нужно применить TO_NUMBER.

select * from laptop 
where name='lap2'  
and TO_NUMBER(field2) < 15

TO_NUMBER завершается ошибкой в ​​некоторых случаях, когда план запроса решает сначала применить to_number вместо другого фильтра.

ВОПРОСЫ
Это действительный дизайн?
Каковы другие альтернативные способы решения этой проблемы?
Один из наших товарищей по команде предложил создавать таблицы на лету для таких случаев. Это хорошая идея?
Как популярные инструменты ORM предоставляют настраиваемые или гибкие поля для обработки?

Надеюсь, я смог разобраться в этом вопросе.

Извините за такой длинный текст ..

Это заставляет нас использовать TO_NUMBER, когда queryio

Ответы [ 4 ]

4 голосов
/ 28 мая 2010

Это обычная проблема, и нет идеального решения. Пара решений:

1. Определите X полей типа varchar2, Y полей типа type и Z полей типа date. Это потенциально в 3 раза больше числа пользовательских полей, но у вас больше не будет проблем с конвертацией.

Ваш пример будет выглядеть так:

Id Name field_char1  field2_char2 field_char3 ... field_num1 field_num2 ...
1  lap1 lappy        lappy        lappy       ... 12         13     
2  lap2 lappy2       lappy2       lapp2       ... 13         12

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

2. Определите поля X типа varchar2 и примените биективную функцию для хранения поля числа или даты (например, Дата может быть сохранена как YYYYMMDDHH24miss). Вам также понадобится дополнительное поле, которое будет определять контекст строки. Вы бы применили функцию to_number или to_char только тогда, когда строки имеют хороший тип.

Ваш пример:

Id Name context field1  field2 field3  field4 field5
1  lap1 type A  lappy   lappy  12      13     lappy
2  lap2 type B  lappy2  13     lappy2  lapp2  12

Вы можете запросить таблицу, используя DECODE или CASE:

SELECT * 
  FROM laptop
 WHERE CASE WHEN context = 'TYPE A' THEN to_number(field3) END = 12

Второй дизайн - тот, который используется в Oracle Financials ERP (среди прочих). Контекст позволяет вам определять ограничения CHECK с этим дизайном (например, CHECK (CASE WHEN context = 'TYPE A' THEN to_number(field3) > 0) для обеспечения целостности.

3 голосов
/ 28 мая 2010

Это распространенный сценарий для термоусадочных приложений, где он представляет единственную возможность для настройки модели данных. Но с пуристической точки зрения это плохая практика. Потому что, если столбец может содержать «27-мая-2010» или 178.50 или «красный барсук», то, очевидно, он зависит от чего-то внешнего от базы данных, чтобы придать ему значение.

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

Итак, как лучше всего с этим бороться? Настраиваемые функции для ваших пользовательских столбцов:

SQL> create or replace function get_number
  2      ( p_str in varchar2 )
  3      return number
  4      deterministic
  5  is
  6      return_value number;
  7  begin
  8      begin
  9          return_value := to_number(trim(p_str));
 10      exception
 11          when others then
 12              return_value := null;
 13      end;
 14      return return_value;
 15  end;
 16  /

Function created.

SQL>

Мы можем построить функцию на основе этого столбца для производительности:

SQL> create index t42_flex_idx on t42 ( get_number( flex_col))
  2  /

Index created.

SQL>

Итак, учитывая эти данные испытаний ....

SQL> select * from t42
  2  /

        ID FLEX_COL
---------- ------------------------------
         1 27-MAY-2010
         2 138.50
         3 Red badger
         2 23

SQL>

... вот как это работает:

SQL> select * from t42
  2  where get_number(flex_col) < 50
  3  /

        ID FLEX_COL
---------- ------------------------------
         2 23

SQL>
0 голосов
/ 27 мая 2010

Не могли бы вы создать график XML в слое кода и сохранить его в поле типа SYS.XMLTYPE?

http://www.oracle -base.com / статьи / 9i / XMLTypeDatatype.php

Это позволит вам строго ввести (в XML) ваши значения и сохранить значимую структуру.

0 голосов
/ 27 мая 2010

Если все типы столбцов будут определены во время создания таблицы, тогда создание таблиц на лету будет мне полезно.

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

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