2012-01-27 2 views
20

с использованием SQL Server 2005 с пакетом обновления 4 (SP4), и я создаю таблицу базы данных.Должен ли я использовать тип данных SQL_Variant?

Вот таблица DDL

CREATE TABLE CPSync4D.ProjectProfilerOption 
(
    ProjectProfilerOptionID  INT IDENTITY(1,1) CONSTRAINT PK_ProjectProfilerOption_ProjectProfilerOptionID PRIMARY KEY 
    ,ProjectID     INT CONSTRAINT FK_ProjectProfilerOption_Project_ProjectID FOREIGN KEY(ProjectID) REFERENCES CPSync4D.Project(ProjectID) ON DELETE CASCADE 
    ,ProfilerOptionID   TINYINT CONSTRAINT FK_ProjectProfilerOption_ProfilerOption_ProfilerOptionID FOREIGN KEY(ProfilerOptionID) REFERENCES CPSync4D.ProfilerOption (ProfilerOptionID) 
    ,ProfilerOptionValue   sql_variant NOT NULL 

) 
Go 

profileroptionvalue столбец может содержать либо строку до 30 символов, целого числа или десятичных значений, например, значения «ProfilerValueType» или 12.52 или 20 и т. д. (не более двух десятичных знаков и целочисленных значений меньше 100)

Должен ли я использовать sql_variant или varchar (30) ...? Я никогда раньше не использовал sql_variant и не был уверен в том, что вы не используете его в плане дизайна базы данных.

Все подводные камни использования SQL_VARIANT ... с .net кода

ответ

15

10 reasons to explicitly convert SQL Server data types

По общему правилу, следует избегать использования типа данных в SQL Server sql_variant . Sql_variant, кроме того, является памятью:

  • Варианты не могут быть частью первичного или внешнего ключа. (это не относится к SQL Server 2005. См. Обновление ниже)
  • Варианты не могут быть частью вычисленного столбца.
  • Варианты не будут работать с LIKE в предложении WHERE.
  • Поставщики OLE DB и ODBC автоматически конвертируют варианты в nvarchar (4000) - ouch!

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

Я раньше не использовал sql_variant, но с учетом этих ограничений и последствий для производительности, я сначала рассмотрю альтернативы.

После будет моим самым наименее предпочтительным решением

  • Просто создайте три колонки. 3 Различные типы данных (должны) означают три разных способа интерпретации как на стороне клиента, так и на стороне сервера.
  • Если это не вариант, используйте столбец VARCHAR, чтобы вы могли, по крайней мере, использовать инструкции LIKE.
  • Используйте тип данных sql_variant.

РедактироватьCudo, чтобы ta.speot.это

Variants can be part of a primary of foreign key

Уникальный, первичный или внешний ключ может включать в себя столбцы типа sql_variant, но общая длина значений данных, которые составляют ключ конкретной строки не должно быть больше максимальной длины индекса . Это 900 байт

+1

Первые две причины не так, как в SQL 2012. Это работает просто отлично: объявить @t в виде таблицы (k1 SQL_VARIANT первичного ключа, k2 как k1) значений @t вставки («ААА») выберите * из @t – DenNukem

+9

Как правило, вы всегда должны быть очень подозрительны к любому объяснению, которое начинается с «Как общее правило». ;-) И, нет ... это не память, особенно когда вы используете его, чтобы заменить 3 столбца различными типами данных, как вы предложили. Это также справедливый бит быстрее, чем переход через VARCHAR. Для этого есть много хороших применений. Просто большинство людей не знают, что это такое. ;-) –

+0

@JeffModen - У вас есть ссылка, сравнивающая память и скорость 'sql_variant' с другими типами данных? –

5

Я знаю, что мой ответ немного поздний, но создаваемая здесь таблица немного похожа на таблицу конфигурации приложения. В качестве альтернативы предложенным предложениям давайте подумаем о том, чтобы не ограничивать себя 30 или даже 8000 персонажами. Давайте также сделаем его немного более самостоятельным и определяемым пользователем.

С учетом этих соображений, почему бы не сохранить информацию о профиле как тип данных XML, который бы даже разрешил несколько уровней настроек? Вероятно, вам больше не понадобятся такие столбцы, как ProfilerOptionID, и, возможно, вы сможете получить это до одной простой таблицы управления.

+0

+1 Это была бы хорошая альтернатива. –

3

Стоит отметить, что невозможно скопировать колонку sql_variant неявно.

например. Создать резервную схему CPSync4D.ProjectProfilerOption под названием CPSync4D.ProjectProfilerOption_bkp

, а затем

Insert into CPSync4D.ProjectProfilerOption_bkp 
(
    ProjectProfilerOptionID 
    ,ProjectID 
    ,ProfilerOptionID 
    ,ProfilerOptionValue 
) 
SELECT 
    ProjectProfilerOptionID 
    ,ProjectID 
    ,ProfilerOptionID 
    ,ProfilerOptionValue 
FROM CPSync4D.ProjectProfilerOption 

Все значения для ProfilerOptionValue в таблице резервного копирования будет VARCHAR

Обратите также внимание: я сказал, что SQL_Variant не может использоваться в репликации, но это не так.. Конечно, это можно сделать с SQL 2008 R2 (я использую), потому что я только что это сделал, но это может быть верны для более старых версий. (У меня нет старых версий для проверки, поэтому не могу подтвердить или опровергнуть это).

Что же правда, так это то, что если вы выполняете репликацию таблицы с помощью SQL-варианта в ней и имеете много данных, а затем что-то пойдет не так, и вам нужно исправить данные вручную, тогда у вас может быть неприятная штука SQL для записи. Это связано с тем, что при копировании данных вы не можете копировать несколько базовых типов в один и тот же оператор копирования. Я предполагаю, что эта репликация не имеет этой проблемы, поскольку она не копирует несколько строк (с очевидным исключением моментального снимка, но использует bcp).

ps. Я понимаю, что это старый пост, но поставил это здесь для других будущих посетителей с тем же вопросом.

Смежные вопросы