15

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

  • Id - 整数 (PK)
  • 键 - 唯一,varchar(15)
  • 值 - varchar(1000)

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

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

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


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

4

4 回答 4

10

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 框架没有很好地支持
于 2013-01-17T16:25:59.463 回答
8

如果将类型更改为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。

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

当然,“专注于 SQLServer 的人”(阅读:DBA)根本不喜欢它 :-) 在 SQL Server 方面,sql_variant使用起来不是很实用(如评论中所述),但如果您将其保留为不透明的“东西”,不必在 SQL 过程代码中使用它,我认为没关系。因此,它在 .NET/OO 编程方面更具优势。

于 2013-01-15T10:49:21.127 回答
0

我还没有看到它被提到过,所以我会提到一个相当常见的解决这个问题的方法是这样的表格:

  • Id - 整数 (PK)
  • 键 - 唯一,varchar(15)
  • ValueType - 整数(0 - 字符串,1 - 整数,3 - 浮点数)(可选)
  • 字符串值 - varchar(1000)
  • IntValue - 整数
  • FloatValue - 双倍

优点:

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

缺点:

  • 在您使用此表的任何地方,您都必须确保您/获取/设置正确的值列
  • 如果您决定需要/想要 ValueType 列,则必须确保正确获取/设置它。
于 2013-01-18T19:18:40.490 回答
0

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

我感到困惑的是,您提到了 varchar(1000),然后“哎哟”了返回转换后的 nvarchar(4000)。

我首先要说的是,整个世界终于停止使用本地和有限的字符集并决定全力以赴使用 Unicode 和 UTF-8,这是一件好事,所以你应该更喜欢 nvarchar 而不是 varchar 和 ntext 而不是文本。

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

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

ntext 也非常适合 .NET,因为它的字符串始终采用 Unicode。在 .NET 中从字符串到 int 的转换也比 sql server 更快。

希望这可以帮助

于 2013-01-17T14:58:56.377 回答