База данных SQL, хранящий различные типы значений (в или моделируемые как одно поле)

StackOverflow https://stackoverflow.com/questions/5818138

Вопрос

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

Variables
    ID
    Name

VariableValuesLink
    ID
    IDVars
    IDVals

Values
    IDvals

ValuesValueLink
    ID
    IDvals
    IDval

ValuesInt
    IDval
    IntVal

ValuesFloat
    IDval
    FloatVal

ValuesDouble
    IDval
    DoubleVal

etc...
etc...
etc...
etc...

Цель состоит в том, чтобы получить что -то вроде этого:

Variable: 
    ezas123
Values:
    1 (Int)
    2.0 (Float)
    3.0 (Double)

Variable:
    QuickFox
Values:
    The (TinyText)
    Quick (TinyText)
    Brown (TinyText)
    Fox (TinyText)
    Jumped (TinyText)
    Over (TinyText)
    The (TinyText)
    Lazy (TinyText)
    Dog (TinyText)

Variable:
    Pangrams
Values:
    The Quick Brown Fox Jumped Over The Lazy Dog (Text)
    How quickly daft jumping zebras vex (Text)

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

Variable    Value
ezas123     1
ezas123     2.0
ezas123     3.0
QuickFox    The
QuickFox    Quick
QuickFox    Brown
QuickFox    Fox
QuickFox    Jumped
QuickFox    Over
QuickFox    The
QuickFox    Lazy
QuickFox    Dog
Pangrams    The Quick Brown Fox Jumped Over The Lazy Dog
Pangrams    How quickly daft jumping zebras vex
Это было полезно?

Решение

Пара очков:

  • В вашем примере переменная EZAS123 имеет три значения с разными типами данных, что означает, что сама переменная фактически не имеет определенного типа данных. Это, вероятно, вызовет проблемы вниз по течению и, вероятно, укажет, что данные довольно плохо определены. Я бы посмотрел на включение ограничения, что все значения для данной переменной должны иметь одинаковый тип данных.

  • Запрос SQL Хогана указывает на то, что всякий раз, когда вы перечисляете значения по тому, как вы запросили (то есть по переменным с различными типами данных) вам придется отменить результат в Varchar или аналогично отобразить его (поскольку у вас не может быть значения с разными типами данных в одном и том же выводом). Имея это в виду, вам действительно нужны разные типы данных, или тип Varchar хорошо работает для всех данных, с которыми вы имеете дело?

Если необходимы различные типы, я бы посмотрел на размещение всех различных Intval, Floatval, DoubleVal, ... столбцов в одну таблицу. Определения вашей таблицы могут выглядеть примерно как:

Variables
      ID          NOT NULL
     ,Name        NOT NULL
     ,DataType    NOT NULL CHECK (DataType IN ('INT','FLOAT','DOUBLE','TEXT'))  
   ,CONSTRAINT PK_Variables PRIMARY KEY (ID)
   ,CONSTRAINT UQ_Variables_1 UNIQUE (Name)
   ,CONSTRAINT UQ_Variables_2 UNIQUE  (ID,DataType)

    Values
      IDvals      NOT NULL
     ,ID          NOT NULL
     ,DataType    NOT NULL CHECK (DataType IN ('INT','FLOAT','DOUBLE','TEXT'))
     ,IntVal      NULL
     ,FloatVal    NULL
     ,DoubleVal   NULL
     ,TextVal     NULL
   ,CONSTRAINT PK_Values PRIMARY KEY (IDvals)
   ,CONSTRAINT FK_Values_Variable FOREIGN KEY (ID,DataType) REFERENCES Variables(ID,DataType)
   ,CONSTRAINT CH_Values CHECK ( NOT(DataType <> 'INT'    AND IntVal     IS NOT NULL)  AND
                                 NOT(DataType <> 'FLOAT'  AND FloatVal   IS NOT NULL)  AND
                                 NOT(DataType <> 'DOUBLE' AND DoubleVal  IS NOT NULL)  AND
                                 NOT(DataType <> 'TEXT'   AND TextVal    IS NOT NULL)
                                )
  • Уникальное ограничение на переменные (ID, DataType), вероятно, потребуется (СУБД?), Чтобы позволить вам сделать его предметом FK;
  • Ограничения проверки гарантируют, что используются только допустимые типы данных и что могут быть заполнены единственные правильные столбцы значения;
  • Наличие данных дата в значениях, а также переменных означает, что комбинация FK и проверки может использоваться для обеспечения того, чтобы все значения для данной переменной имели одинаковый тип данных, а не необходимость использовать триггеры или логику приложения.

Запрос против столов, а затем выглядит примерно как:

SELECT v.name as Variable,
       COALESCE(cast(a.IntVal       as varchar(max)),
                cast(a.FloatVal     as varchar(max)),
                cast(a.DoubleVal    as varchar(max)),
                cast(a.TextVal      as varchar(max)),
                '') as Value
FROM 
Variables V
JOIN Values a on V.ID = a.ID AND v.DataType = a.DataType

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

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

Другие советы

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

Variable
    ID
    Name

ValuesInt
    IDvariable
    IntVal

ValuesFloat
    IDvariable
    FloatVal

ValuesDouble
    IDvariable
    DoubleVal

etc...
etc...
etc...

Как ваш SQL прост:

select v.name as Variable,
       coalesce(cast(vi.IntVal as varchar(max)),
                cast(vf.FoatVal as varchar(max)),
                cast(vd.DoubleVal as varchar(max)),
                '') as Value
From Variable V
JOIN ValuesInt vi on V.ID = vi.IDvariable
JOIN ValuesFloat vf on V.ID = vf.IDvariable
JOIN ValuesDouble vd on V.ID = vd.IDvariable
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top