[sql] 소수 열에 돈 저장-정밀도와 스케일은 무엇입니까?

데이터베이스에 돈 값을 저장하기 위해 10 진수 열을 사용하고 있으며 오늘 사용할 정밀도와 스케일이 궁금합니다.

고정 너비의 문자 열이 더 효율적이라고 가정하기 때문에 십진 열에 대해서도 마찬가지라고 생각했습니다. 그렇습니까?

그리고 어떤 정밀도와 스케일을 사용해야합니까? 나는 24/8의 정밀도를 생각하고있었습니다. 그 잔인 함은 충분하지 않습니까?


이것이 내가하기로 결정한 것입니다.

  • 거래 테이블 자체에 전환율 (해당되는 경우)을 플로트로 저장
  • 계정 테이블에 통화 저장
  • 거래 금액은 DECIMAL(19,4)
  • 변환율을 사용한 모든 계산은 내 응용 프로그램에서 처리되므로 반올림 문제를 계속 제어합니다.

전환율에 대한 플로트는 대부분 참조 용이므로 문제가되지 않는다고 생각합니다. 어쨌든 10 진수로 캐스팅 할 것입니다.

소중한 의견을 보내 주셔서 감사합니다.



답변

한 가지 크기의 제품을 찾고 있다면 DECIMAL(19, 4)인기있는 선택 이라고 제안 합니다 (Google이 신속하게 처리합니다). 나는 이것이 구 VBA / 액세스 / 제트 통화 데이터 타입에서 유래 한 것으로 생각합니다. DecimalVB6 / VBA6 / Jet 4.0에서는 ‘버전 1.0’스타일 (즉, 완전히 구현되지 않음) 만있었습니다.

고정 소수점 10 진수 값 을 저장 하기위한 경험의 규칙은 실제로 반올림을 허용하는 데 필요한 것보다 적어도 하나 이상의 소수점을 저장하는 것입니다. Currency프런트 엔드 의 이전 유형을 DECIMAL(19, 4)백 엔드의 유형으로 매핑하는 이유 중 하나 Currency는 은행원의 성격을 반올림 했기 때문입니다.DECIMAL(p, s) 입니다.

저장소에 여분의 소수점 이하 자릿수를 DECIMAL사용하면 공급 업체의 기본값을 사용하지 않고 사용자 지정 반올림 알고리즘을 구현할 수 있습니다 (그리고 은행가의 반올림은 놀랍습니다. .

그렇습니다 DECIMAL(24, 8). 대부분의 통화는 소수점 이하 네 자리로 인용됩니다. 8 (또는 그 이상)의 진수 규모가 어디 상황을 알고 있다 필요한 있지만 이것은 ‘정상적인’금액 (소수 자릿수 네 자리)이 비례하여 소수점 이하 자릿수가 그에 따라 감소해야 함을 암시합니다 (또한 고려하십시오) 이러한 상황에서 부동 소수점 유형). 그리고 오늘날 아무도 십진수 정밀도 24를 요구할만큼 많은 돈이 없습니다 🙂

그러나 모든 규모에 맞는 접근법이 아닌 일부 연구는 순서대로 진행될 수 있습니다. GAAP, EU 등 적용 가능한 회계 규칙에 대해 설계자 또는 도메인 전문가에게 문의하십시오. 소수의 다섯 자리로 반올림하기위한 명시적인 규칙을 사용하여 일부 EU 내 국가 간 전송을 모호하게 기억하므로 DECIMAL(p, 6)저장에 사용 합니다. 회계사는 일반적으로 소수점 이하 네 자리를 선호하는 것 같습니다.


PS MONEY반올림시 정확성과 심각한 문제가 있으므로 SQL Server의 데이터 유형을 피하십시오 . 이식성 등과 같은 다른 고려 사항도 있습니다. Aaron Bertrand의 블로그를 참조하십시오 .


하드웨어 디자이너가 그것을 인용했기 때문에 마이크로 소프트와 언어 디자이너는 은행가의 반올림을 선택했습니다. 예를 들어 IEEE (Institute of Electrical and Electronics Engineers) 표준에 명시되어 있습니다. 그리고 수학자들이 선호하기 때문에 하드웨어 설계자들이 그것을 선택했습니다. Wikipedia를 참조하십시오 . 역설 : 1906 년 확률과 오류 이론은 이것을 ‘컴퓨터의 규칙'(계산을 수행하는 인간을 의미하는 “컴퓨터”)이라고 불렀습니다.


답변

우리는 최근 여러 통화로 값을 처리하고 그 사이에서 변환 해야하는 시스템을 구현했으며 어려운 몇 가지 사항을 알아 냈습니다.

돈에 부동 소수점 숫자를 사용하지 마십시오

부동 소수점 산술은 무언가를 망칠 때까지 눈에 띄지 않을 수있는 부정확성을 소개합니다. 모든 값은 정수 또는 고정 소수점 형식으로 저장해야하며, 고정 소수점 형식을 사용하기로 선택한 경우 해당 형식이 후드에서 수행하는 작업을 정확히 이해해야합니다 (예 : 내부적으로 정수 또는 부동 소수점을 사용합니까) 유형).

계산 또는 변환이 필요한 경우 :

  1. 값을 부동 소수점으로 변환
  2. 새로운 가치를 계산
  3. 숫자를 반올림하고 다시 정수로 변환

3 단계에서 부동 소수점 숫자를 다시 정수로 변환 할 때는 캐스트하지 말고 수학 함수를 사용하여 먼저 반올림하십시오. round특별한 경우에는 floor또는 일 수 있지만 이것은 보통 일 것이다 ceil. 차이점을 알고 신중하게 선택하십시오.

값과 함께 숫자 유형을 저장하십시오.

하나의 통화 만 처리하는 경우에는 이것이 중요하지 않을 수 있지만 여러 통화를 처리하는 데 중요했습니다. USD, GBP, JPY, EUR 등과 같은 통화에 3 자 코드를 사용했습니다.

상황에 따라 다음을 저장하는 것이 도움이 될 수도 있습니다.

  • 숫자가 세전 또는 후인지 여부 및 세율
  • 숫자가 변환의 결과인지 여부 및 변환 된 결과

당신이 다루고있는 숫자의 정확도 한계를 아십시오

실제 가치의 경우 가장 작은 통화 단위만큼 정확해야합니다. 이것은 1 센트, 1 페니, 엔, 펜 등의 값이 없다는 것을 의미합니다. 아무 이유없이 그 값보다 높은 정확도로 값을 저장하지 마십시오.

내부적으로 더 작은 값을 처리하도록 선택할 수 있으며,이 경우 다른 통화 값 유형입니다 . 코드가 어느 것을 알고 있고 혼동하지 않도록하십시오. 여기에서도 부동 소수점 값을 사용하지 마십시오.


이러한 규칙을 모두 추가하여 다음 규칙을 결정했습니다. 실행 코드에서 통화는 가장 작은 단위의 정수를 사용하여 저장됩니다.

class Currency {
   String code;       //  eg "USD"
   int value;         //  eg 2500
   boolean converted;
}

class Price {
   Currency grossValue;
   Currency netValue;
   Tax taxRate;
}

데이터베이스에서 값은 다음 형식으로 문자열로 저장됩니다.

USD:2500

그것은 $ 25.00의 가치를 저장합니다. 통화를 처리하는 코드가 데이터베이스 계층 자체 내에있을 필요가 없으므로 모든 값을 먼저 메모리로 변환 할 수 있기 때문에 그렇게 할 수있었습니다. 다른 상황은 의심 할 여지없이 다른 솔루션에 적합합니다.


그리고 내가 일찍 그것을 명확하게 하지 않은 경우, float을 사용하지 마십시오!


답변

MySQL에서 돈을 처리 할 때 돈 가치의 정밀도를 알고 있으면 DECIMAL (13,2)을 사용하고 충분히 빠른 대략적인 가치를 원한다면 DOUBLE을 사용하십시오. 따라서 응용 프로그램이 최대 1 조 달러 (또는 유로 또는 파운드)의 돈 값을 처리해야하는 경우 다음과 같이 작동합니다.

DECIMAL(13, 2)

또는 GAAP 를 준수해야하는 경우 다음을 사용하십시오.

DECIMAL(13, 4)


답변

소수점 이하 4 자리는 세계에서 가장 작은 통화 하위 단위를 저장하는 정확도를 제공합니다. 소액 결제 (nanopayment ?!) 정확성이 필요한 경우 추가로 이월 할 수 있습니다.

나는 또한 DECIMALDBMS 특정 돈 유형을 선호 합니다. 응용 프로그램 IMO에서 이러한 종류의 논리를 유지하는 것이 더 안전합니다. 같은 줄을 따라 또 다른 방법은 단순히 응용 프로그램 수준에서 수행되는 사람의 가독성 (¤ = 통화 기호)을 위해 ¤unit.subunit으로 서식을 지정하는 [long] 정수를 사용하는 것입니다.


답변

SQL Server의 money 데이터 유형은 소수점 이하 4 자리입니다.

SQL Server 2000 온라인 설명서에서 :

통화 데이터는 양 또는 음의 금액을 나타냅니다. Microsoft® SQL Server ™ 2000에서 화폐 데이터는 money 및 smallmoney 데이터 유형을 사용하여 저장됩니다. 화폐 데이터는 소수점 이하 네 자리까지 정확하게 저장할 수 있습니다. money 데이터 유형을 사용하여 -922,337,203,685,477.5808에서 +922,337,203,685,477.5807 (값을 저장하려면 8 바이트 필요) 범위의 값을 저장하십시오. smallmoney 데이터 유형을 사용하여 -214,748.3648에서 214,748.3647 범위의 값을 저장하십시오 (값을 저장하려면 4 바이트 필요). 더 많은 소수 자릿수가 필요한 경우 대신 십진 데이터 유형을 사용하십시오.


답변

때때로 당신은 센트 미만으로 가야 할 것이고 매우 큰 악마를 사용하는 국제 통화가 있습니다. 예를 들어 고객에게 거래 당 0.088 센트를 청구 할 수 있습니다. 내 Oracle 데이터베이스에서 열은 NUMBER (20,4)로 정의됩니다


답변

DB에서 어떤 종류의 산술 연산을 수행하려는 경우 (청구 요금 등을 곱하는 등) 아마도 사람들이 제안한 것보다 훨씬 더 정밀한 것을 원할 것입니다. 응용 프로그램 코드에서 배정 밀도 부동 소수점 값보다 작은 것을 사용하려고합니다.