2012-12-11 32 views
13

我现在有一个数据库表设置如下(EAV - 商业上的原因是有效的):在SQL Server中使用sql_variant over varchar有什么好处吗?

  • 标识 - 一个int(PK)
  • 键 - 独特,VARCHAR(15)
  • 价值 - VARCHAR( 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 vs varchar(1000)


更清楚,我读的地方,SQL_VARIANT被返回的数据类型为nvarchar(4000)返回给客户端进行调用(哎哟)!但是,在返回之前我不能将它转换成它的类型吗?显然,我的代码必须进行调整,以将值存储为对象而不是字符串值。我想,在我目前的情况下,使用sql_variant与其他类型的优点/缺点是什么?哦,值得一提的是,我计划存储的日期时间,字符串和数值类型(int,decimal等)在value列中;我不打算存储和blob或图像等

+1

As [Aaron Bertrand在他的*糟糕的习惯中提到踢 - 使用错误的数据类型*](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/12/bad-habits-to -kick-using-the-wrong-data-type.aspx):*全部使用SQL_VARIANT * - 它不是**一个好主意。不要使用它。你没有得到任何好处 - 但有很多缺点... –

+0

除了声明sql_variant是坏的,你是否声明varchar(1000)是在我确切的情况下去的方式? –

+0

您如何看待使用sql_variant会增强您的表格? –

回答

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设置为不透明值,不要使用DbType。

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

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

1

sql_variant类型有其局限性,正如Zarathos所描述的那样。

我觉得困惑的是你提到varchar(1000),然后'ouch'关于返回一个转换的nvarchar(4000)。

我首先要说的是,整个世界终于停止使用本地和有限的字符集并决定全部使用Unicode和UTF-8是一件好事,因此您应该更喜欢nvarchar over varchar和ntext over文本。

而且返回值是nvarchar(4000)而不是nchar(4000)。不同之处在于,任何varchar的大小都是可变的,而普通类型char的大小是固定的。返回char(4000)的元组将会发送大量的空垃圾,但使用varchar这不是问题。

好的。但是什么是适合你的适当的数据类型?我会推荐ntext。 明天1000人今天可能是10,000人。如果你有很多文本没有编制索引,那么你的数据库可能不应该决定什么限制。这只是文字。

ntext也适合.NET,因为它的字符串总是以Unicode编码。 .NET中的字符串转换为int的速度也快于sql server。

希望这有助于

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框架
2

我看不出它已经没有提到,所以我会提到这一问题相当普遍的做法是这样的一个表:

  • 标识 - INT (PK)
  • 键 - 独特,VARCHAR(15)
  • 值类型 - 整数(0 - 字符串,1 - 整数,3 - 浮动)(可选)
  • 的StringValue - VARCHAR(1000)
  • INTVALUE - Intege [R
  • 的floatValue - 双人

优点:

  • 数据保存在其适当的形式(存储整数为字符串浪费很多位)
  • 你可以等,其中左看中查询(key,5)='SHOES'和IntValue> 5
  • ValueType列仅用于在键上使用前缀/后缀(用于检索键集),并且该集可以是混合类型。即WHERE左(键,4)= '大小' 和值类型= 1

缺点:

  • 无处不在,你使用这个表,你必须确保你/获取/设置正确的值列
  • 如果您决定需要/需要ValueType列,则必须确保您正确设置/设置。
+5

通过'ValueType'列和填充'StringValue','IntValue'和'FloatValue'之间的选择,您已经成功地重新创建了一个'sql_variant',它有更多的工作要使用,并且功能更少。 –

相关问题