Подтвердить что ты не робот

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

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

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

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

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

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


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

4b9b3361

Ответ 1

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

Вставить в значения MySettings ('Name', '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

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

  • не очень быстро
  • не поддерживается форматами ORM

Ответ 2

Если вы измените тип на 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.

Ответ 3

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

  • Id - int (PK)
  • Ключ - уникальный, varchar (15)
  • ValueType - Integer (0 - String, 1 - Integer, 3 - Float) (необязательно)
  • StringValue - varchar (1000)
  • IntValue - Integer
  • FloatValue - Double

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

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

Недостатки:

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

Ответ 4

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

То, что я сбиваю с толку, заключается в том, что вы упоминаете varchar (1000), а затем "ouch" о возврате преобразованного nvarchar (4000).

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

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

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

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

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