База данных SQL, хранящий различные типы значений (в или моделируемые как одно поле)
-
26-10-2019 - |
Вопрос
В базе данных я хочу иметь возможность назначать значения различного типа переменным в таблице переменных. Так мне нужна отдельная таблица значений для каждого типа значения? Если это так, я не уверен, как вы бы на самом деле связали значения с правильной таблицей и, следовательно, правильным значением. Как я могу достичь того, что я после?
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