我应该使用SQL_Variant数据类型吗?

时间:2012-01-27 20:13:28

标签: sql sql-server sql-server-2005 database-design

使用带有SP4的SQL Server 2005,我正在设计一个数据库表。

这是表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代码

的任何陷阱

3 个答案:

答案 0 :(得分:18)

10 reasons to explicitly convert SQL Server data types

  

作为一般规则,您应该避免使用SQL Server的sql_variant   数据类型。除了作为记忆猪,sql_variant是有限的:

     
      
  • 变体不能是主键或外键的一部分。 (这不适用于SQL Server 2005.请参阅下面的更新)
  •   
  • 变量不能是计算列的一部分。
  •   
  • 变量不适用于WHERE子句中的LIKE。
  •   
  • OLE DB和ODBC提供程序自动将变体转换为nvarchar(4000) - 哎哟!
  •   
     

为避免出现问题,请始终将sql_variant数据类型显式转换为   你用它们。使用您喜欢的任何方法,只是不要尝试使用   未转换的sql_variant数据类型。

我之前没有使用过sql_variant但是考虑到这些限制和性能影响,我首先会考虑替代方案。

以下是我最不喜欢的解决方案

  • 只需创建三个不同的列。 3不同的数据类型(应该)是指在客户端和服务器端解释它的3种不同方式。
  • 如果这不是一个选项,请使用VARCHAR列,这样您至少可以使用LIKE语句。
  • 使用sql_variant数据类型。

编辑 Cudo's to ta.speot.is

Variants can be part of a primary of foreign key

  

唯一,主键或外键可以包含类型的列   sql_variant,但是组成的数据值的总长度   特定行的键不应超过a的最大长度   指数。这是900字节

答案 1 :(得分:6)

我知道我的答案有点晚了但是这里制作的表看起来有点像应用程序配置表。作为给出的建议的替代方案,让我们考虑不要将自己限制在30或甚至8000个字符。我们也让它更自包含,用户可以定义。

考虑到这些想法,为什么不将“配置文件”信息保存为XML数据类型,甚至允许多级设置?您可能不再需要像ProfilerOptionID这样的列,并且可能能够将其归结为一个简单的控制表。

答案 2 :(得分:3)

值得注意的是,无法隐式复制sql_variant列。

e.g。创建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 Variant的表并且拥有大量数据然后出现问题并且您需要手动修复数据,那么您可能会遇到一个令人讨厌的问题。 SQL写。这是因为在复制数据时,您无法在同一副本语句中使用多种基本类型进行复制。我想复制没有这个问题,因为它不复制多行(明显的例外是快照,但是使用了bcp)。

PS。我知道这是一篇很老的帖子,但是这个问题也适用于其他未来的访问者。