我现在有一个数据库表设置如下(EAV - 商业上的原因是有效的):
- ID - INT(PK)
- 键 - 独特,VARCHAR(15)
- 价值 - VARCHAR(1000)
这让我在混合值添加到我的DATABSE以键/值对。 例如:
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,小数等); 我不存储和BLOB或图像或计划等。
有关SQL变种的好处是,你可以存储多种类型的列和你保持类型的信息。
INSERT INTO MySettings值( '名称', '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
不幸的是这有几个缺点:
- 不是非常快
- 不能很好的ORM框架支持
如果更改类型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的为重点的家伙”(读:数据库管理员)不喜欢它:-)在SQL Server端, sql_variant
不太实际使用(如在评论中指出),但如果你把它作为不透明的“东西”,并没有在SQL程序代码中使用它,我认为这是好的。 因此,它是在.NET / OO编程方面更加具有优势。
该SQL_VARIANT类型有其局限性如Zarathos描述良好。
我感到迷惑的是,你提到VARCHAR(1000),然后“哎哟”有关返回转换为nvarchar(4000)。
我会说,这是一件好事,对整个世界终于利用本地和有限的字符集,停止,决定全力以赴在Unicode和UTF-8开始,所以你应该更喜欢在为nvarchar的varchar和ntext文本上。
和返回类型为nvarchar(4000),而不是NCHAR(4000)。 不同的是,任何VARCHAR是 - 在大小可变的,而普通类型char被固定在尺寸。 CHAR(4000)的返回的元组将派出大量的空浪费,但VARCHAR,这不是一个问题。
好的。 但是,这将是一个正确的数据类型是你吗? 我会建议NTEXT。 什么是今天的1000可能是明天10000。 如果你有“大量的文字”你是不是索引,那么也许你的数据库不应该决定限制可能是什么。 这只是文字。
NTEXT也与.NET非常适合,因为它的字符串始终以Unicode。 从字符串到int转换也快于.NET比由SQL Server来完成。
希望这可以帮助
我看不出它已经没有提到,所以我会提到这一问题相当普遍的做法是这样的一个表:
- ID - INT(PK)
- 键 - 独特,VARCHAR(15)
- 值类型 - 整数(0 - 字符串,1 - 整数,3 - 浮动)(可选)
- 的StringValue - VARCHAR(1000)
- INTVALUE - 整数
- 的floatValue - 双
好处:
- 数据被保存在它的适当的形式(存储整数作为字符串浪费了大量的比特)
- 你可以像WHERE左(键,5)=“鞋”,和INTVALUE> 5看中查询
- 该值类型列只是您使用的是你的钥匙前缀/后缀有用的(以获取密钥组)和设定可能是混合型的。 即,其中左(键,4)=“尺寸”和值类型= 1
缺点:
- 无处不在,你使用这个表,你必须保证你/获取/设置正确的值列
- 如果你决定你需要/想要的值类型列,你必须确保你得到/设置正确。