将英镑存入数据库

时间:2017-04-29 11:57:07

标签: sql sql-server

我从未在数据库中使用过下面的货币。我做了一些研究,告诉我你应该使用Decimal数据类型。请参阅下面的DDL:

create table dbCurrency (id int not null identity, CurrencyValue decimal (4,2), primary key (id))
insert into dbCurrency (CurrencyValue) values (50);
insert into dbCurrency (CurrencyValue) values (20);
insert into dbCurrency (CurrencyValue) values (10);
insert into dbCurrency (CurrencyValue) values (5);
insert into dbCurrency (CurrencyValue) values (2);
insert into dbCurrency (CurrencyValue) values (1);
insert into dbCurrency (CurrencyValue) values (0.5);
insert into dbCurrency (CurrencyValue) values (0.2);
insert into dbCurrency (CurrencyValue) values (0.1);
insert into dbCurrency (CurrencyValue) values (0.05);
insert into dbCurrency (CurrencyValue) values (0.02);
insert into dbCurrency (CurrencyValue) values (0.01);

存储所有英国货币。这是正确的方法吗?我问的原因是因为与我交谈的人建议数据类型应为:decimal (5,2)而不是decimal (4,2). He knew I was storing currencies up to £50.

另外,假设我有两个C#小数:

decimal first;
decimal second;
decimal third;

说我想将第一个小数除以第二个小数,以产生第三个小数。第三个小数也是c#decimal数据类型吗?第一个小数值总是大于第二个小数,结果可能是一小部分。第一个和第二个小数是货币值。

2 个答案:

答案 0 :(得分:0)

您选择了decimal()而不是money / smallmoney,因此您已经超过了第一道障碍。

一般情况下,建议您选择decimal()(与numeric()相同的精度和比例。在这种情况下,decimal(4,2)很好,因为最大存储值不会超过precisionscale

decimal(4,2)decimal(5,2)decimal(9,2)之间没有存储空间大小差异。

decimal存储空间大小基于precision

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

在SQL Server中执行某些操作时,precisionscale可能会发生变化。在您的示例中,当您将decimal1除以decimal2时,您的返回类型将为decimal,而precisionscale将由下表确定:

+------------------------------+-------------------------------------+----------------+
|          Operation           |          Result precision           | Result scale * |
+------------------------------+-------------------------------------+----------------+
| e1 + e2                      | max(s1, s2) + max(p1-s1, p2-s2) + 1 | max(s1, s2)    |
| e1 - e2                      | max(s1, s2) + max(p1-s1, p2-s2) + 1 | max(s1, s2)    |
| e1 * e2                      | p1 + p2 + 1                         | s1 + s2        |
| e1 / e2                      | p1 - s1 + s2 + max(6, s1 + p2 + 1)  | max(6,s1+p2+1) |
| e1 union|except|intersect e2 | max(s1, s2) + max(p1-s1,p2-s2)      | max(s1, s2)    |
| e1 % e2                      | min(p1-s1, p2 -s2) + max( s1,s2 )   | max(s1, s2)    |
+------------------------------+-------------------------------------+----------------+
  

*结果精度和标度的绝对最大值为38.当结果精度大于38时,相应的标度会减小,以防止结果的整数部分被截断。

因此,选择decimal(4,2)可能会产生一些影响,具体取决于值所涉及的操作,但两者之间的任何性能差异都可以忽略不计。

参考:

在C#中,小数除以小数后返回小数;小数除以整数返回小数;小数除以浮点数返回错误而没有显式转换。

答案 1 :(得分:0)

存储所有英国货币。这是正确的方法。

您不存储货币 - 您存储假定货币的面额(或官方票据和硬币的面值)。这是否正确"取决于你的建模 - 没有人,但你知道。我同意@SqlZim关于数据类型的看法。

我对标识列的用处有很强的保留意见。是否有目的或者您是否将标识列作为标准做法打入每个表格?至少,您应该强制使用自然键。

根据维基百科的说法,你可能会遗漏一些价值观,并且在价值方面,票据和硬币之间存在一些重叠。