在SQL Server中使用sql_variant而不是varchar有什么好处吗?

时间:2012-12-11 15:32:31

标签: c# performance sql-server-2012 varchar sql-variant

我目前有一个数据库表设置如下(EAV - 业务原因有效):

  • Id - int(PK)
  • Key - unique,varchar(15)
  • 价值 - varchar(1000)

这允许我将混合值作为键/值对添加到我的数据库中。例如:

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

在我的C#代码中,我使用reader.GetString(2);使用ADO.Net将值作为字符串检索,然后让我的代码在其他地方根据需要进行转换,例如...... Int32.ParseInt(myObj.Value);。我正在考虑通过将值列更改为sql_variant数据类型来增强我的表,但我不知道这会带来什么好处?基本上,让我的列属于sql_variant vs varchar(1000)是否有任何好处?


为了更清楚,我在某处读到sql_variant以nvarchar(4000)的形式返回给进行调用的客户端(ouch)!但是,在返回它之前,我不能把它转换成它的类型吗?显然,我的代码必须进行调整,以将值存储为对象而不是字符串值。我想,在我目前的情况下,使用sql_variant与其他类型相比有哪些优点/缺点?哦,值得一提的是我计划存储的所有内容都是值列中的日期时间,字符串和数字类型(int,decimal等);我不计划存储和blob或图像等。

4 个答案:

答案 0 :(得分:9)

关于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

不幸的是,这有几个缺点:

  1. 不是很快
  2. 没有得到ORM框架的良好支持

答案 1 :(得分:7)

如果您将类型更改为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设置为opaque值,不要使用DbType。

具有各种(标准)类型作为价值的EAV是我个人认为sql_variant很有趣的一个案例。

当然“以SQLServer为中心的人”(读取:DBA)根本不喜欢它:-)在SQL Server端,sql_variant使用起来不太实际(如评论中所述) ,但如果你把它作为一个不透明的“东西”,并且不必在SQL过程代码中使用它,我认为没关系。因此,它在.NET / OO编程方面更具优势。

答案 2 :(得分:1)

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,因为它的字符串总是使用Unicode。 从字符串到int的转换在.NET中也比sql server更快。

希望这有帮助

答案 3 :(得分:1)

我没有看到它已被提及,所以我会提到这个问题的一个相当常见的方法就是这样一个表:

  • Id - int(PK)
  • Key - unique,varchar(15)
  • ValueType - 整数(0 - 字符串,1 - 整数,3 - 浮点数)(可选)
  • StringValue - varchar(1000)
  • IntValue - 整数
  • FloatValue - Double

优点:

  • 以适当的形式保存数据(将字符串存储为字符串会浪费很多位)
  • 你可以做一些奇特的查询,比如WHERE left(key,5)='SHOES'和IntValue> 5
  • ValueType列仅对您在键上使用前缀/后缀(检索键集)有用,并且该集可以是混合类型。即WHERE left(key,4)='Size'和ValueType = 1

缺点:

  • 您使用此表的任何地方都必须确保您/获取/设置正确的值列
  • 如果您确定需要/想要ValueType列,则必须确保正确设置/设置它。