对于价格和价值,使用varchar over decimal是否有任何优势

时间:2010-08-03 13:14:16

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

我和我的朋友争论反对他在varchar中存储价格,价值和其他类似信息的建议。

我的观点是基于

  1. 由于我们需要来回投射,计算将变得困难。
  2. 数据的完整性将会丢失。
  3. 指数表现不佳
  4. 排序和聚合函数也需要转换
  5. 等。等

    但是他说,在他以前的工作中,每个人都习惯将这些值存储在varchar中,因为DB和APP之间的通信在这种方法中非常有效。 (我仍然不能接受这个)

    在varchar中存储这些值确实有一些优势吗?

    注意:我不是在讨论PhoneNo,ID,邮政编码,SSN等专栏。我知道varchar最适合那些。这些列是基于值的,并且肯定会以某种方式参与计算。

7 个答案:

答案 0 :(得分:10)

完全没有。

尝试重新输入值,并查看丢失的数据量。

DECLARE @foo TABLE (bar varchar(30))
INSERT @foo VALUES (11.2222222222)
INSERT @foo VALUES (22.3333333333)
INSERT @foo VALUES (33.1111111111)
SELECT CAST(CAST(bar AS float) AS varchar(30)) FROM @foo

我还要提到他的当前的就业方式不同......他不再是之前的就业......

答案 1 :(得分:4)

我认为使用APPROPRIATE(在本例中为十进制)数据类型的原因很大一部分是为了防止无效数据。没有什么可以阻止某人输入“国王”作为varchar领域的价格。

答案 2 :(得分:3)

我看不到任何优点,也有一大堆非常严重的缺点 - 最紧迫的是性能(特别是在排序时)。

考虑是否要获取N个最昂贵产品的列表,并将价格存储为VARCHAR。以下是一些示例值(按降序排序)

SELECT Price FROM Table ORDER BY Price DESC

Price
-----

90
600
50
1000

糟糕!排序顺序是错误的! (字母数字排序,而不是值排序)。

如果我们想要正确地进行排序,那么这意味着我们需要在开始时用零填充值,或者在排序之前将每个值转换为double - 但是如果我们必须在每一行上进行转换,这意味着SQL服务器无法使用统计信息来预测结果将是什么!这反过来意味着性能极差,可能是表扫描。

答案 3 :(得分:2)

正如克拉根指出的那样,分类不一定按照正确的顺序出现。

比较也不一定有效。如果一个字段定义为,例如,十进制(8,2),我给它值“37.20”,后来我写“select ... where price = 37.2”,结果将为真。但是,如果我存储varchar 37.20并将其与37.2进行比较,则它将不相等。同样,如果一个或另一个有前导零。

您可以通过让应用程序确保始终存储具有固定小数位数的数字并使用前导零填充来解决这些问题。哦,并确保你有关于存储减号的一致惯例。但是,应用程序中写入此字段的每个位置都必须确保它遵循完全相同的规则。我们当然可以做到这一点,但为什么呢?如果我们只声明字段数字,数据库引擎将为我们做。就像,是的,我可以用一把剪刀修剪我的草坪,但为什么我要这样做呢?

我不明白你的朋友说的优势应该是什么。应用和数据库之间的通信更轻松?怎么样?也许他正在使用一些无法从DB中读取数值的非常规语言或数据库接口。我从来没有遇到过这个问题。实际上只是说这让我想知道这是不是发生了什么:在他以前的公司他们使用的某些语言或工具因为实施问题而无法从数据库中读取小数,这是他们获得它的唯一方法工作是将所有数字声明为varchar,现在他走开了,认为这是一个普遍好主意。

答案 4 :(得分:1)

好的。一个字回答。不要

对于对性能有影响的正确数据类型(SQL Optimizer对INT VS VARCHAR的工作方式不同),数据一致性和完整性等,您是正确的

如果我们所需要的只是VARCHAR我不认为我们曾经发明过其他类型。 SQL不是动态类型的。静态类型使优化更好,索引页面更小,查询运算符更有效。

消费者需要所有字符串作为输入,这不是源的问题。消费者可以进行类型检查和消费数据。数据库应始终具有正确的类型。

(忘记在INT和VARCHAR之间进行选择我会说你还应该考虑是否应该有INT或TINYINT)这些考虑会产生很大的不同

答案 5 :(得分:0)

数据类型最好存储在与两个不同系统之间的类型匹配的字段中。在这种情况下,您将从.Net对象引用到MS SQL服务器。数据完整性丢失以及需要将数据类型转换为可用表单是正确的。至于其他类型,如电话号码,邮政编码,SSN等;他们也将受益于专用数据类型。这些存储在VARCHAR / NVARCHAR中的主要原因是由于每个系统中不需要的不同可能性的数量。但是,如果您有一个常用的类型并且想要约束它,则可以构建名为User-defined types的自定义数据类型,以将该数据存储在SQL Server中。 (更有趣的是CLR定义的类型参见code project上的示例。)

答案 6 :(得分:0)

我可以看到使用任何类型的可变大小的字符串格式的唯一优势是,如果字段必须容纳未知数量的附加信息。例如,“49.95 @ 1 / 39.95 @ 5 / 29.95 @ 20 / 14.95 @ 100,match = true / 24.95 @ 100”表示此特定产品的价格点为1,5,20和100个单位,以及只有当所有商品都相同时,才能获得最佳100单位价格。使用字符串来存储这些东西是很棘手的,但是如果价格点的数量是开放式的,那么使用可变大小的字段可能比必须创建另一个每个产品/价格点组合一行的表更好。如果您确实采用了这种方法,那么对数据使用XML序列化可能是好事,而不是如上所示的特殊事物。在某些情况下,特殊方法可能允许更快的解析,但如果事情真的是开放式的,那么维护就会变得非常痛苦。

附录:如果您希望能够根据价格进行任何类型的排序或搜索,则需要为此分别设置列。如果您想允许用户例如在100件混合/匹配数量中找到十个最便宜的项目,并且数据库包含10,000个可能的项目,使用varchar存储数据满足查询的唯一方法是读取所有l0,000个项目并评估最佳价格给予限制。如果用户只能根据少量的价格/限制组合进行查询,那么为每个用户设置一个列以允许直接查询可能会有所帮助。