Есть ли какие-либо преимущества использования sql_variant по сравнению с varchar в SQL Server?

В настоящее время у меня есть настройки таблицы базы данных следующим образом (EAV - деловые причины действительны):

  • Id - int (PK)
  • Ключ - уникальный, varchar(15)
  • Значение - варчар (1000)

Это позволяет мне добавлять смешанные значения в мою базу данных в виде пар ключ / значение. Например:

1   | 'Some Text'      | 'Hello World'
2   | 'Some Number'    | '123456'
etc.

В моем коде C# я использую ADO.Net используя reader.GetString(2); чтобы получить значение в виде строки, а затем мой код в другом месте преобразовать его, как необходимо, например... Int32.ParseInt(myObj.Value);, Я смотрю на улучшение моей таблицы путем возможного изменения столбца значения на sql_variant тип данных, но я не знаю, какая польза от этого будет? В принципе, есть ли преимущество в том, чтобы мой столбец значений был sql_variant против varchar(1000)?


Чтобы быть более ясным, я где-то читал, что sql_variant возвращается как nvarchar(4000) обратно клиенту, делающему вызов (ой)! Но разве я не мог привести его к его типу, прежде чем вернуть? Очевидно, мой код должен быть скорректирован, чтобы хранить значение как объект вместо строкового значения. Я думаю, каковы преимущества / недостатки использования sql_variant против какого-то другого типа в моей нынешней ситуации? Да, и стоит упомянуть, что все, что я планирую сохранить, это datetime, строки и числовые типы (int, decimal и т. Д.) В столбце значений; Я не планирую хранить и блобить или изображения и т. Д.

4 ответа

Преимущество варианта sql в том, что вы можете хранить несколько типов в столбце и хранить информацию о типах.

Вставьте в MySettings значения ("Имя", "MyName"); Вставить в MySettings значения ('ShouesNumber',45); Вставить в значения MySettings ("MyDouble",31.32);

Если вы хотите получить тип:

select SQL_VARIANT_PROPERTY ( value , 'BaseType' ) as DataType,* from mysettings

и у тебя есть:

Datatype Name          Value
-----------------------------
varchar  Name          MyName
int      ShoesNumber   45
numeric  MyDouble      31.32

К сожалению, у этого есть несколько недостатков:

  1. не очень быстро
  2. не очень хорошо поддерживается фреймворками ORM

Если вы измените тип на sql_variant, вам придется использовать метод IDataRecord.GetValue. Это сохранит тип полностью.

Так что в.NET это позволит вам иметь такой код:

// read an object of SQL underlying data type 'int' stored in an sql_variant column
object o = myReader.GetValue(); // o.GetType() will be System.Int32

// read an object of SQL underlying data type '(n)varchar' or '(n)char' stored in an sql_variant column
object o = myReader.GetValue(); // o.GetType() will be System.String

// read an object of SQL underlying data type 'datetime' stored in an sql_variant column
object o = myReader.GetValue(); // o.GetType() will be System.DateTime

etc...

Конечно, это предполагает, что вы делаете то же самое при сохранении. Просто установите SqlParameter.Value в непрозрачное значение, не используйте DbType.

EAV с различными (стандартными) типами в качестве значения - это единственный случай, когда я лично думаю sql_variant Интересно.

Конечно, "ребятам, ориентированным на SQLServer" (читай: администраторам баз данных) это совсем не нравится:-) На стороне SQL Server, sql_variant не очень практично в использовании (как отмечено в комментариях), но если вы сохраняете это как непрозрачную "вещь" и не должны использовать его в коде процедуры SQL, я думаю, это нормально. Таким образом, это больше преимущество на стороне программирования.NET/OO.

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

  • Id - int (PK)
  • Ключ - уникальный, varchar (15)
  • ValueType - Integer (0 - строка, 1 - целое число, 3 - число с плавающей запятой) (необязательно)
  • StringValue - varchar (1000)
  • IntValue - Integer
  • FloatValue - Двухместный

Преимущества:

  • Данные сохраняются в соответствующей форме (хранение значений в виде строк приводит к потере большого количества битов)
  • Вы можете выполнять модные запросы, например, ГДЕ слева (key,5) = 'SHOES' и IntValue>5
  • Столбец ValueType полезен только в том случае, если вы используете префиксы / суффиксы в своих ключах (для получения наборов ключей), и набор может быть смешанного типа. то есть ГДЕ осталось (key,4) = "Размер" и ValueType = 1

Недостатки:

  • Везде, где вы используете эту таблицу, вы должны убедиться, что вы / получили / установите правильный столбец Значение
  • Если вы решите, что вам нужен / нужен столбец ValueType, вы должны убедиться, что вы его получили / установили правильно.

Тип sql_variant имеет свои ограничения, хорошо описанные Zarathos.

Что меня смущает, так это то, что вы упоминаете varchar(1000), а затем 'ой' о возвращении преобразованного nvarchar(4000).

Я хотел бы начать с того, что хорошо, что весь мир, наконец, прекратил использовать локальные и ограниченные кодировки и решил пойти ва-банк на Unicode и UTF-8, поэтому вы должны предпочесть nvarchar вместо varchar и ntext над текстом.

И возврат nvarchar (4000), а не nchar(4000). Разница в том, что любой varchar имеет переменный размер, в то время как обычный тип char имеет фиксированный размер. Возвращение кортежей char (4000) будет отправлять много пустых отходов, но с varchar это не проблема.

Хорошо. Но что для вас будет правильным типом данных? Я бы порекомендовал ntext. То, что было 1000 сегодня, может быть 10 000 завтра. Если у вас есть "много текста", который вы не индексируете, то, возможно, ваша база данных не должна решать, каким может быть ограничение. Это просто текст.

ntext также хорошо подходит для.NET, поскольку его строки всегда в Unicode. Преобразование из строки в int также быстрее в.NET, чем это делает сервер SQL.

Надеюсь это поможет

Другие вопросы по тегам