我很好奇货币数据类型和十进制(19,4)之类的数据类型之间是否有真正的区别(我相信这是货币内部使用的)。
我知道钱是特定于SQL Server的。我想知道是否有令人信服的理由来选择一个而不是另一个;大多数SQL Server样本(例如AdventureWorks数据库)使用金钱而不是小数来表示价格信息。
我是否应该继续使用货币数据类型,或者使用十进制是否有好处?金钱可以输入的字符更少,但这不是一个有效的理由:)
我很好奇货币数据类型和十进制(19,4)之类的数据类型之间是否有真正的区别(我相信这是货币内部使用的)。
我知道钱是特定于SQL Server的。我想知道是否有令人信服的理由来选择一个而不是另一个;大多数SQL Server样本(例如AdventureWorks数据库)使用金钱而不是小数来表示价格信息。
我是否应该继续使用货币数据类型,或者使用十进制是否有好处?金钱可以输入的字符更少,但这不是一个有效的理由:)
当前回答
SQLMenace说钱是不精确的。但是你不能把钱乘以/除以钱!3美元乘以50美分等于多少?150 dollarcents ?你用标量乘(除)钱,结果应该是小数。
DECLARE
@mon1 MONEY,
@mon4 MONEY,
@num1 DECIMAL(19,4),
@num2 DECIMAL(19,4),
@num3 DECIMAL(19,4),
@num4 DECIMAL(19,4)
SELECT
@mon1 = 100,
@num1 = 100, @num2 = 339, @num3 = 10000
SET @mon4 = @mon1/@num2*@num3
SET @num4 = @num1/@num2*@num3
SELECT @mon4 AS moneyresult,
@num4 AS numericresult
结果在正确的结果:
moneyresult numericresult --------------------- --------------------------------------- 2949.8525 2949.8525
钱是好的,只要你不需要超过4个十进制数字,你要确保你的标量(不代表钱)是小数。
其他回答
之前所有的帖子都提出了有效的观点,但有些并没有准确地回答这个问题。
问题是:当我们已经知道钱是一种不那么精确的数据类型,并且在复杂的计算中使用它会导致错误时,为什么有人更喜欢钱?
当你不需要进行复杂的计算,并且可以用这种精度来换取其他需求时,你就会使用金钱。
例如,当您不需要进行这些计算,而需要从有效的货币文本字符串中导入数据时。此自动转换仅适用于MONEY数据类型:
SELECT CONVERT(MONEY, '$1,000.68')
我知道你可以制作自己的导入程序。但有时您不希望使用全球特定的区域设置格式重新创建导入例程。
另一个例子,当你不需要进行这些计算(你只需要存储一个值),需要节省1个字节(金钱需要8个字节,而十进制(19,4)需要9个字节)。在一些应用中(快速CPU,大内存,慢IO),比如只是读取大量的数据,这也可以更快。
作为对其他答案主旨的反驳。看金钱的诸多好处…数据类型!在SQLCAT的关系引擎指南中
我要具体指出以下几点
Working on customer implementations, we found some interesting performance numbers concerning the money data type. For example, when Analysis Services was set to the currency data type (from double) to match the SQL Server money data type, there was a 13% improvement in processing speed (rows/sec). To get faster performance within SQL Server Integration Services (SSIS) to load 1.18 TB in under thirty minutes, as noted in SSIS 2008 - world record ETL performance, it was observed that changing the four decimal(9,2) columns with a size of 5 bytes in the TPC-H LINEITEM table to money (8 bytes) improved bulk inserting speed by 20% ... The reason for the performance improvement is because of SQL Server’s Tabular Data Stream (TDS) protocol, which has the key design principle to transfer data in compact binary form and as close as possible to the internal storage format of SQL Server. Empirically, this was observed during the SSIS 2008 - world record ETL performance test using Kernrate; the protocol dropped significantly when the data type was switched to money from decimal. This makes the transfer of data as efficient as possible. A complex data type needs additional parsing and CPU cycles to handle than a fixed-width type.
所以这个问题的答案是“视情况而定”。对于某些算术操作,您需要更加小心,以保持精度,但您可能会发现,出于性能考虑,这样做是值得的。
You shouldn't use money when you need to do multiplications / divisions on the value. Money is stored in the same way an integer is stored, whereas decimal is stored as a decimal point and decimal digits. This means that money will drop accuracy in most cases, while decimal will only do so when converted back to its original scale. Money is fixed point, so its scale doesn't change during calculations. However because it is fixed point when it gets printed as a decimal string (as opposed to as a fixed position in a base 2 string), values up to the scale of 4 are represented exactly. So for addition and subtraction, money is fine.
小数点内部以10为底表示,因此小数点的位置也以10为底数为基础。这使得它的小数部分准确地代表了它的值,就像货币一样。不同之处在于十进制的中间值可以保持38位的精度。
对于浮点数,值以二进制形式存储,就像它是一个整数一样,并且小数点(或二进制,嗯,)点的位置相对于表示该数字的位。因为它是一个二进制小数点,以10为基数的数字在小数点后失去精度。1/5,或0.2,不能用这种方式精确地表示。货币和十进制都不受这个限制。
将货币转换为十进制,执行计算,然后将结果值存储回货币字段或变量中,这非常简单。
从我的角度来看,我希望发生在数字上的事情不需要太多思考就能发生。如果所有的计算都要转换成十进制,那么对我来说,我只想用十进制。我会保留money字段用于显示。
就尺寸而言,我看不出有多大差别来改变我的想法。Money需要4 - 8个字节,而decimal可以是5、9、13和17。9个字节可以覆盖8个字节的货币所能覆盖的全部范围。索引方面(比较和搜索应该具有可比性)。
SQLMenace说钱是不精确的。但是你不能把钱乘以/除以钱!3美元乘以50美分等于多少?150 dollarcents ?你用标量乘(除)钱,结果应该是小数。
DECLARE
@mon1 MONEY,
@mon4 MONEY,
@num1 DECIMAL(19,4),
@num2 DECIMAL(19,4),
@num3 DECIMAL(19,4),
@num4 DECIMAL(19,4)
SELECT
@mon1 = 100,
@num1 = 100, @num2 = 339, @num3 = 10000
SET @mon4 = @mon1/@num2*@num3
SET @num4 = @num1/@num2*@num3
SELECT @mon4 AS moneyresult,
@num4 AS numericresult
结果在正确的结果:
moneyresult numericresult --------------------- --------------------------------------- 2949.8525 2949.8525
钱是好的,只要你不需要超过4个十进制数字,你要确保你的标量(不代表钱)是小数。
永远不要使用金钱。它不精确,纯粹是垃圾;总是使用十进制/数字。
运行这个来看看我的意思:
DECLARE
@mon1 MONEY,
@mon2 MONEY,
@mon3 MONEY,
@mon4 MONEY,
@num1 DECIMAL(19,4),
@num2 DECIMAL(19,4),
@num3 DECIMAL(19,4),
@num4 DECIMAL(19,4)
SELECT
@mon1 = 100, @mon2 = 339, @mon3 = 10000,
@num1 = 100, @num2 = 339, @num3 = 10000
SET @mon4 = @mon1/@mon2*@mon3
SET @num4 = @num1/@num2*@num3
SELECT @mon4 AS moneyresult,
@num4 AS numericresult
输出:2949.0000 2949.8525
有些人说钱不能一分一分
这是我计算相关性的一个问题,把它换成金钱会得到错误的结果。
select t1.index_id,t2.index_id,(avg(t1.monret*t2.monret)
-(avg(t1.monret) * avg(t2.monret)))
/((sqrt(avg(square(t1.monret)) - square(avg(t1.monret))))
*(sqrt(avg(square(t2.monret)) - square(avg(t2.monret))))),
current_timestamp,@MaxDate
from Table1 t1 join Table1 t2 on t1.Date = traDate
group by t1.index_id,t2.index_id