Sql server 您应该在SQL Server中选择MONEY还是DECIMAL(x,y)数据类型?
我很好奇Sql server 您应该在SQL Server中选择MONEY还是DECIMAL(x,y)数据类型?,sql-server,types,Sql Server,Types,我很好奇money数据类型和类似于decimal(19,4)的数据类型之间是否存在真正的区别(我相信money内部使用的数据类型) 我知道money是特定于SQL Server的。我想知道是否有令人信服的理由选择其中一个而不是另一个;大多数SQL Server示例(例如AdventureWorks数据库)使用货币,而不是十进制来表示价格信息 我应该继续使用money数据类型,还是使用decimal有好处?“钱”可以输入的字符更少,但这不是一个合理的理由:)永远不要使用钱。它不精确,而且纯粹是垃圾
money
数据类型和类似于decimal(19,4)
的数据类型之间是否存在真正的区别(我相信money内部使用的数据类型)
我知道money
是特定于SQL Server的。我想知道是否有令人信服的理由选择其中一个而不是另一个;大多数SQL Server示例(例如AdventureWorks数据库)使用货币
,而不是十进制
来表示价格信息
我应该继续使用money数据类型,还是使用decimal有好处?“钱”可以输入的字符更少,但这不是一个合理的理由:)永远不要使用钱。它不精确,而且纯粹是垃圾;始终使用十进制/数字 运行此命令以了解我的意思:
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
有些人说你不会把钱除以钱:
这里是我的一个查询,用于计算相关性,将其更改为money会给出错误的结果
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
他说金钱是不精确的。但是你不能用钱来乘/除钱!3美元乘以50美分是多少?150美元?你用标量乘/除货币,标量应该是小数
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
moneyresult数字结果
--------------------- ---------------------------------------
2949.8525 2949.8525
money
只要您不需要超过4位小数,并且您确保您的标量(不代表金钱)是decimal
s.我刚才看到了这个博客条目:
这基本上是说钱有一个精确的问题
declare @m money
declare @d decimal(9,2)
set @m = 19.34
set @d = 19.34
select (@m/1000)*1000
select (@d/1000)*1000
对于
money
类型,您将获得19.30而不是19.34。我不确定是否有一个应用程序场景将资金分成1000个部分进行计算,但这个示例确实暴露了一些局限性。我们刚刚遇到了一个非常类似的问题,我现在非常喜欢除了在顶级演示之外从不使用资金。由于历史原因,我们有多个表(实际上是销售凭证和销售发票),其中每个表都包含一个或多个货币字段,我们需要执行按比例计算,以计算出发票税总额中有多少与销售凭证上的每一行相关。我们的计算是
vat proportion = total invoice vat x (voucher line value / total invoice value)
这会导致现实世界中的货币/货币计算,从而导致除法部分的比例误差,然后再乘以不正确的增值税比例。当这些价值随后相加时,我们得到的增值税比例总和不等于发票总价值。如果括号中的任何一个值是十进制的(我将把其中的一个转换为十进制),增值税比例将是正确的
当括号不在那里时,我想这是用来工作的,因为涉及的值更大,它有效地模拟了更高的比例。我们添加括号是因为它首先进行乘法运算,在一些罕见的情况下,乘法运算会破坏可用的精度,但现在这导致了更常见的错误。我意识到WayneM已经声明他知道钱是SQL Server特有的。然而,他问,是否有任何理由使用货币而不是十进制,或者反之亦然,我认为一个明显的理由仍然应该说明,那就是使用十进制意味着,如果您不得不更改您的DBMS,则无需担心一件事——这可能会发生
让您的系统尽可能灵活 如果你不知道自己在做什么,一切都是危险的 即使是高精度的十进制类型也无法保存日期:
declare @num1 numeric(38,22)
declare @num2 numeric(38,22)
set @num1 = .0000006
set @num2 = 1.0
select @num1 * @num2 * 1000000
1.000000嗯,我喜欢
钱
!它比十进制便宜一个字节,而且计算速度更快,因为(在幕后)加法和减法运算本质上是整数运算@SqlNemage的例子对不知情者是一个很好的警告,同样可以应用于INT
egers,结果为零。但这并不是不在适当的地方使用整数的理由
因此,当你处理的是
MONEY
时,使用MONEY
是完全“安全”且合适的,并根据它遵循的数学规则使用它(与INT
eger相同)
如果SQL Server将MONEY
的除法和乘法提升为DECIMAL
s(或FLOAT
s?)会更好吗?可能吧,但他们没有选择这样做;在分割时,他们也没有选择将INT
egers提升为FLOAT
s
货币
没有精度问题;在计算过程中,DECIMAL
s可以使用更大的中间类型,这只是使用该类型的一个“功能”(我不确定该“功能”扩展了多远)
要回答这个特定的问题,一个“令人信服的理由”?好的,如果你想在一个SUM(x)
中获得绝对的最大性能,其中x
可以是DECIMAL
或MONEY
,那么MONEY
将具有优势
另外,别忘了它是较小的表亲,SMALLMONEY
——只有4个字节,但它的最大值为214748.3647
——这对钱来说是相当小的,所以通常不适合
为了证明使用较大中间类型的正确性,如果将中间类型显式指定给变量,DECIMAL
也会遇到同样的问题:
declare @a decimal(19,4)
declare @b decimal(19,4)
declare @c decimal(19,4)
declare @d decimal(19,4)
select @a = 100, @b = 339, @c = 10000
set @d = @a/@b
set @d = @d*@c
select @d
产生
2950.0000
(好的,所以至少DECIMAL
四舍五入,而不是MONEY
截断,与整数相同)。我找到了在精度主题中使用DECIMAL优于MONEY的原因
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 浮动结果>1
只要测试一下,然后做出决定。你不应该在需要花钱的时候花钱
SELECT CONVERT(MONEY, '$1,000.68')