我很好奇货币数据类型和十进制(19,4)之类的数据类型之间是否有真正的区别(我相信这是货币内部使用的)。
我知道钱是特定于SQL Server的。我想知道是否有令人信服的理由来选择一个而不是另一个;大多数SQL Server样本(例如AdventureWorks数据库)使用金钱而不是小数来表示价格信息。
我是否应该继续使用货币数据类型,或者使用十进制是否有好处?金钱可以输入的字符更少,但这不是一个有效的理由:)
我很好奇货币数据类型和十进制(19,4)之类的数据类型之间是否有真正的区别(我相信这是货币内部使用的)。
我知道钱是特定于SQL Server的。我想知道是否有令人信服的理由来选择一个而不是另一个;大多数SQL Server样本(例如AdventureWorks数据库)使用金钱而不是小数来表示价格信息。
我是否应该继续使用货币数据类型,或者使用十进制是否有好处?金钱可以输入的字符更少,但这不是一个有效的理由:)
当前回答
基于我个人的专业知识和经验,我想对金钱和数值给出不同的看法。我的观点是金钱,因为我已经用了很长一段时间,从来没有真正使用数值…
资金支持:
Native Data Type. It uses a native data type (integer) as the same as a CPU register (32 or 64 bit), so the calculation doesn't need unnecessary overhead so it's smaller and faster... MONEY needs 8 bytes and NUMERICAL(19, 4) needs 9 bytes (12.5% bigger)... MONEY is faster as long as it is used for it was meant to be (as money). How fast? My simple SUM test on 1 million data shows that MONEY is 275 ms and NUMERIC 517 ms... That is almost twice as fast... Why SUM test? See next Pro point Best for Money. MONEY is best for storing money and do operations, for example, in accounting. A single report can run millions of additions (SUM) and a few multiplications after the SUM operation is done. For very big accounting applications it is almost twice as fast, and it is extremely significant... Low Precision of Money. Money in real life doesn't need to be very precise. I mean, many people may care about 1 cent USD, but how about 0.01 cent USD? In fact, in my country, banks no longer care about cents (digit after decimal comma); I don't know about US bank or other country...
钱反对:
有限的精度。MONEY只有四位数(在逗号之后)精度,所以在进行除法等运算之前必须对其进行转换…但话又说回来,钱不需要这么精确,它是作为货币使用的,而不仅仅是一个数字……
但是…很大,但这里甚至是您的应用程序涉及到真钱,但不要在很多SUM操作中使用它,比如在会计中。如果你用了很多除法和乘法,那么你就不应该用MONEY…
其他回答
作为对其他答案主旨的反驳。看金钱的诸多好处…数据类型!在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.
所以这个问题的答案是“视情况而定”。对于某些算术操作,您需要更加小心,以保持精度,但您可能会发现,出于性能考虑,这样做是值得的。
我找到了在精确度科目中使用十进制而不是货币的原因。
DECLARE @dOne DECIMAL(19,4),
@dThree DECIMAL(19,4),
@mOne MONEY,
@mThree MONEY,
@fOne FLOAT,
@fThree FLOAT
SELECT @dOne = 1,
@dThree = 3,
@mOne = 1,
@mThree = 3,
@fOne = 1,
@fThree = 3
SELECT (@dOne/@dThree)*@dThree AS DecimalResult,
(@mOne/@mThree)*@mThree AS MoneyResult,
(@fOne/@fThree)*@fThree AS FloatResult
十进制结果 > 1.000000
MoneyResult > 0.9999
FloatResult > 1
只需测试一下,然后做出决定。
如果你不知道自己在做什么,一切都是危险的
即使是高精度的十进制类型也无法扭转局面:
declare @num1 numeric(38,22)
declare @num2 numeric(38,22)
set @num1 = .0000006
set @num2 = 1.0
select @num1 * @num2 * 1000000
1.000000 <-应该是0.6000000
货币类型是整数
smallmoney和decimal(10,4)的文本表示可能看起来很像,但这并不意味着它们可以互换。当您看到日期存储为varchar(10)时,您会感到畏缩吗?这是一样的。
在幕后,money/smallmoney只是一个bigint/int。money的文本表示中的小数点在视觉上是无用的,就像yyyy-mm-dd日期中的破折号。SQL实际上并没有在内部存储这些数据。
关于十进制和金钱,选择任何适合你需要的。货币类型的存在是因为将会计值存储为单位的1/ 10000000的整数倍数是非常常见的。此外,如果您正在处理实际的货币和计算,而不仅仅是简单的加减法,那么您不应该在数据库级别上这样做!在应用程序级别使用支持Banker's舍入的库进行计算(IEEE 754)
我刚看到这个博客:SQL Server中的金钱vs.十进制。
这基本上是说金钱有一个精确的问题……
declare @m money
declare @d decimal(9,2)
set @m = 19.34
set @d = 19.34
select (@m/1000)*1000
select (@d/1000)*1000
对于货币类型,你将得到19.30而不是19.34。我不确定是否存在将钱分成1000份进行计算的应用场景,但这个示例确实暴露了一些局限性。
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个十进制数字,你要确保你的标量(不代表钱)是小数。