我应该使用什么数据类型来存储货币价值?

时间:2009-08-31 01:15:34

标签: sql sql-server sql-server-2008

我读过我应该使用,但在今天快节奏的世界里,现在可能已经过时了。

我应该使用什么?

5 个答案:

答案 0 :(得分:13)

Papuccino,

除非您确定您计划进行的唯一算术是加法和减法,否则我不建议使用money和s​​mallmoney类型。如果您可能正在处理汇率,百分比等问题,那么您可能会面临这些类型的实际问题。

这里只是一个小例子,告诉你在涉及分割时使用money,decimal和float之间的区别。有可能提出一些例子,其中差异更为显着。

declare @m1 money, @m2 money, @m3 money
declare @d1 decimal(19,4), @d2 decimal(19,4), @d3 decimal(19,4)
declare @f1 float, @f2 float, @f3 float;
set @m1 = 1.00;
set @m2 = 345.00;
set @m3 = @m1/@m2;
set @d1 = 1.00;
set @d2 = 345.00;
set @d3 = @d1/@d2;
set @f1 = 1.00;
set @f2 = 345.00;
set @f3 = @f1/@f2;
select @m3, @d3, @f3;

结果:0.0028 0.0029 0.00289855072463768

根据行业的不同,可能会有一些指导原则或法规可帮助您确定正确的数据类型。没有一个正确的答案。

补充说明:

你说金钱/金钱不应该是钱是正确的,但是SQL Server(莫名其妙地)产生了这样的结果:从两个货币价值的商中输入货币。这是假的,但正如你从下面的例子中看到的那样,这是你得到的,即使它没有意义:

declare @m1 money, @m2 money;
declare @d1 decimal(19,4), @d2 decimal(19,4);
set @m1 = 1.00;
set @m2 = 345.00;
set @d1 = 1.00;
set @d2 = 345.00;
select @m1/@m2, @d1/@d2

结果:0.0028 0.0028985507246376811

类型货币的结果为0.0028,比正确结果少3-4%。

当然,在很多情况下您需要划分货币值。使用货币类型的危险在于商是错误的类型(并且答案与正确的类型不够接近)。需要划分货币的问题示例:

假设您兑换320元,银行给您47.3美元。您获得的汇率是多少?

假设您投资23美元,一年后它的价值为31美元。你的回报率是多少?

这两项计算都需要划分货币值。

答案 1 :(得分:12)

不,钱还应该有用。

答案 2 :(得分:2)

为什么money应该过时?它超过900万亿,是联邦政府预算的数百倍 - 您可能需要存储多少钱? - )(我想也许Zimbabwe dollars可能最终会成为一个问题,但他们继续以数十亿和数万亿的倍数重置它,去年4月它最终被暂停;他们现在使用美元或其他外币进行津巴布韦的支付和会计。)

答案 3 :(得分:1)

我同意用金钱划分的钱是虚假的。但钱除以天是真实的。如果您将少量资金划分为需要花费成本的天数,那么最重要的是要注意这种现象。我将转换/转换为浮动,在最终将最终结果存储到货币数据类型之前进行计算。希望这会有所帮助。

答案 4 :(得分:0)

令我惊讶的是,之前没有人提及它。

money是8个字节。 decimal是5,9,13或17个字节,具体取决于精度(精度不是小数点后的小数位数,它是将存储的最大小数位数,左侧和在小数点右边)。因此,要模仿money支持的值范围(-922,337,203,685,477.5808到922,337,203,685,477.5807),您需要decimal(19,4)

+-------------------+---------------+
| decimal precision | Storage bytes |
+-------------------+---------------+
| 1 - 9             |             5 |
| 10-19             |             9 |
| 20-28             |            13 |
| 29-38             |            17 |
+-------------------+---------------+

如果存储9个字节而不是8个字段似乎没什么大不了的,那么您应该记住money是本机处理器类型,如64位bigint,但{ {1}}不是。这意味着总计数十亿decimal值会比总结money值更快。执行其他计算(例如除法)会产生更大的差异。

在我使用SQL Server 2014 Express的虚拟机上运行这个简单的测试。 decimal是一个包含10,000行的表格,其中dbo.Numbersint的值为1到10,000。

Number

我在SQL Sentry Plan Explorer中运行了它:

CREATE TABLE [dbo].[Numbers](
    [Number] [int] NOT NULL,
CONSTRAINT [PK_Numbers] PRIMARY KEY CLUSTERED 
(
    [Number] ASC
))

两个查询的执行计划相同(嗯,DECLARE @VarM money = 1234.5678; SELECT AVG(@VarM / N1.Number) FROM dbo.Numbers AS N1 CROSS JOIN dbo.Numbers AS N2 ; DECLARE @VarD decimal(19,4) = 1234.5678; SELECT AVG(@VarD / N1.Number) FROM dbo.Numbers AS N1 CROSS JOIN dbo.Numbers AS N2 ; Numbermoney有不同的隐式转换,但运行时间为15秒而40秒。这对我来说非常明显。

money vs decimal

当然,您需要知道decimal只有4位小数。如果执行计算,则需要了解类型(及其优先级,即隐式转换为什么),并通过在需要时将操作数转换为适当的类型来确保中间结果具有适当的类型。此警告适用于任何类型的计算,而不仅仅是money。当您划分两个money值时,您应该知道结果为int,并且不会对int感到惊讶。

相关问题