Следует ли вам выбирать типы данных MONEY или DECIMAL (x, y) в SQL Server?

443

Мне любопытно, есть ли реальная разница между moneyтипом данных и чем-то вроде этого decimal(19,4)(я полагаю, это то, что деньги используют внутри страны).

Я знаю, что moneyэто специфично для SQL Server. Я хочу знать, есть ли веская причина выбрать одно из другого; большинство примеров SQL Server (например, база данных AdventureWorks) используют, moneyа не decimalдля таких вещей, как информация о ценах.

Должен ли я просто продолжать использовать тип данных money, или вместо него есть преимущество использования десятичного числа? Деньги вводят меньше символов, но это не веская причина :)

Уэйн Молина
источник
12
DECIMAL(19, 4) популярный выбор, проверьте это, также проверьте здесь Форматы Мировой валюты, чтобы решить, сколько десятичных знаков использовать, надеюсь, поможет.
Shaijut
Мне было интересно, почему тип данных money имеет 4 знака после запятой, а не 2. т. Е. 100 центов за доллар, поэтому требуются только 2 знака после запятой? Для хранения записей о суммах денег менее $ 9999,99 я собирался использовать десятичный тип данных (6,2). Я не обеспокоен делением или умножением вычислений, просто хранением и суммированием ..
Аллан Ф

Ответы:

326

Никогда не стоит использовать деньги. Это не точно, и это чистый мусор; всегда используйте десятичную / числовую.

Запустите это, чтобы увидеть, что я имею в виду:

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

Некоторым из людей, которые сказали, что вы не делите деньги на деньги:

Вот один из моих запросов для расчета корреляций, и изменение его на деньги дает неверные результаты.

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
SQLMenace
источник
62
«Никогда» - это сильное слово. «Деньги» полезны для приведения результатов к этому типу для отображения пользователю с учетом культурных особенностей, но вы правы, что очень плохо использовать для самих расчетов.
Джоэл Коухорн
37
Ваш пример не имеет смысла, так как никто никогда не умножит два объекта типа деньги. Если вы хотите доказать свою точку зрения, вам нужно сравнить умножение денег на десятичную дробь с умножением десятичной дроби на десятичную.
Брайан
27
... но все еще загадочно, почему деньги * деньги не имеют точности денег.
Обучение
4
@ Обучение: у него есть точность денег. Тем не менее, вы все равно получите ошибки округления, которые могут накапливаться со временем. Десятичный тип не использует двоичную арифметику: он гарантирует, что он получит те же 10 результатов, что и при работе на бумаге.
Джоэл Коухорн
56
Умножение и деление moneyнад в moneyстороне, это «иллюстрация» манипулятивные. Это задокументированный факт, который moneyимеет фиксированную и очень ограниченную точность. В таких случаях нужно сначала умножить, а затем разделить. Измените порядок операторов в этом примере, и вы получите идентичные результаты. По moneyсути, это 64-битное целое, и если бы вы имели дело с целыми числами, вы бы умножили перед делением.
Андрей М
273

SQLMenace говорит, что деньги неточны. Но вы не умножаете / делите деньги на деньги! Сколько стоит 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

moneyЭто хорошо, если вам не нужно больше 4 десятичных цифр, и вы убедитесь, что ваши скаляры - которые не представляют деньги - decimals.

конфигуратор
источник
57
Сколько монет за 1 цент может принести вам долларовая банкнота? ответ на это требует денег / денег.
Обучение
48
@ Обучение в этом случае - результат не денег, а поплавка. (Базовый анализ размеров.)
Ричард,
11
@Learning: Вы спрашиваете базу данных, сколько центов в долларе много? В любом случае, это вернуло бы правильный результат. Его проблема заключалась в том, что деньги / деньги были точными только до четырех цифр (это было 0,2949), а затем при умножении на 10000 они становились 2949,0000.
конфигуратор
26
@mson Он прав и не подвергает личной критике, как вы сделали, основываясь на однострочном замечании, это бесполезно. Если он не делит на 0,01 доллара, а вместо 0,01, то получается 100 долларов вместо 100. В долларе 100 центов, а не 100 центов. Единицы важны! Там определенно большое место для дайвинга и, возможно, умножения денег на деньги.
Андрей
19
Если я хочу потратить 1000 долларов на покупку акций по цене 36 долларов, разве это не законное использование money / money? Ответ - целые единицы без знака доллара, и это правильно! Это вполне разумный сценарий, предполагающий, что из-за странных крайних случаев, подобных этому, moneyэто не очень хороший тип данных для использования, поскольку результат всегда обрезается до соответствия, moneyа не по обычным правилам точности и масштаба. Что если вы хотите рассчитать стандартное отклонение набора moneyзначений? Да, Sqrt(Sum(money * money))(упрощенно) действительно имеет смысл.
ErikE
59

Все опасно, если вы не знаете, что делаете

Даже высокоточные десятичные типы не могут спасти день:

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


Эти moneyтипы являются целыми числами

Текстовые представления smallmoneyи decimal(10,4)могут выглядеть одинаково, но это не делает их взаимозаменяемыми. Вы съеживаетесь, когда видите даты, сохраненные как varchar(10)? Это то же самое.

За кулисами, money/ smallmoneyявляются просто bigint/ int Десятичной точкой в ​​текстовом представлении moneyявляется визуальный пух, точно так же, как тире в дате гггг-мм-дд. SQL на самом деле не хранит их внутри.

Что касается decimalпротив money, выберите все, что подходит для ваших нужд. Эти moneyтипы существуют , так как хранение значений , как что составляет целых кратных 1 / 10000th блока является очень распространенным. Кроме того, если вы имеете дело с реальными деньгами и вычислениями, помимо простого сложения и вычитания, вам не следует делать это на уровне базы данных! Сделайте это на уровне приложения с помощью библиотеки, которая поддерживает округление Банкира (IEEE 754)

скоро
источник
1
Можете ли вы объяснить, что произошло в этом примере?
Сергей Попов
4
Переполнение шкалы. В небольших масштабах числовой (a, b) * числовой (c, d) дает числовой (a-b + c-d + 1, max (b, d)). Однако, если (a + b + c + d)> 38, SQL ограничивает масштаб, теряя точность со стороны дроби для дополнения целочисленной стороны, вызывая ошибку округления.
Anon
Все численные расчеты подвержены потере точности из-за масштабирования: вместо этого вычислите select 1000000 * @ num1 * @ num2
Митч Уит
Пример Anon зависит от версии и базы данных. но дело в том, что будь осторожен, это верно в версии 1.1 sqlanywhere пример действительно дает 0.600000. (Я знаю, что мы говорим о MS SQL здесь). Еще один момент, когда тип денег отсутствует в другой базе данных, есть способы назвать десятичные или числовые значения деньгами, например, создать домен.
gg89
3
Я думаю, что это самый поучительный ответ, потому что вы объяснили не просто ошибки, которые распространяются, но что на самом деле происходит за кулисами, и почему ДЕНЬГИ существуют в первую очередь. Я не уверен, почему потребовалось 4 года, чтобы получить этот ответ, но, возможно, это потому, что слишком много внимания уделяется «проблеме» вычислений, а не столько о том, почему и как деньги, а как десятичные.
Стив Сетер
44

Я понимаю, что WayneM заявил, что он знает, что деньги специфичны для SQL Server. Тем не менее, он спрашивает, есть ли какие-либо причины использовать деньги сверх десятичной или наоборот, и я думаю, что еще нужно указать одну очевидную причину, а именно использование десятичной дроби означает, что беспокоиться о том, стоит ли вам когда-либо менять свою СУБД, - это еще один повод для беспокойства. - что может случиться.

Сделайте ваши системы максимально гибкими!

декан
источник
1
Возможно, но в теории вы могли бы объявить домен с именем Money в другой СУБД (которая поддерживает объявление доменов).
спорщик
Как человек, который в настоящее время конвертирует базу данных SQL Server в Amazon Redshift, я могу заверить, что это подлинная проблема. Старайтесь избегать типов данных, предназначенных для конкретной платформы базы данных, если только для этого нет веских коммерческих причин.
Натан Гриффитс
@Nathn, учитывая слабую систему типов Redshift по сравнению с PostgreSQL или SQL Server, например, без dateтипа, я бы сказал, что у вас всегда будут такие проблемы. Вы должны сказать: «Не используйте устаревшие типы, когда база данных уже предоставляет более совершенные, более совместимые со стандартами типы и предупреждает об устаревших».
Панагиотис Канавос
@PanagiotisKanavos - деньги не устаревают
Мартин Смит
@MartinSmith шокирован, увидев это, поскольку он не может на самом деле обрабатывать денежные значения, такие как BTC в 2017 году. Или различать суммы в фунтах стерлингов и евро - даже если они движутся к паритету: P. Во всяком случае, переход на Redshift
приносит
32

Ну, мне нравится MONEY! Это на байт дешевле чем DECIMAL, и вычисления выполняются быстрее, потому что (под прикрытием) операции сложения и вычитания по существу являются целочисленными операциями. Пример @ SQLMenace, который является отличным предупреждением для незнающих, может в равной степени быть применен к INTegers, где результат будет нулевым. Но это не причина не использовать целые числа - где это уместно .

Таким образом, это совершенно «безопасно» и уместно использовать, MONEYкогда вы имеете дело с тем, с чем вы имеете дело, MONEYи использовать его в соответствии с математическими правилами, которым оно следует (так же, как INTeger).

Было бы лучше, если бы SQL Server способствовал делению и умножению MONEYs на DECIMALs (или FLOATs?) - возможно, но они не решили делать это; и при этом они не решили продвигать INTегеров к FLOATs, разделяя их.

MONEYне имеет проблем с точностью; что DECIMALдобудет иметь больший промежуточный тип , используемый при расчетах просто «функция» с использованием этого типа (и я на самом деле не знаю , как далеко , что «функция» распространяется).

Чтобы ответить на конкретный вопрос, «веская причина»? Ну, если вы хотите абсолютную максимальную производительность вSUM(x) где xможет быть либо, DECIMALлибо MONEY, то MONEYбудет иметь преимущество.

Кроме того, не забывайте, что это двоюродный брат меньшего размера - SMALLMONEYвсего 4 байта, но он имеет максимальный размер 214,748.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усечено - так же, как целое число).

DSZ
источник
21
MONEYна один байт меньше большого DECIMAL , с точностью до 19 цифр. Тем не менее, большинство реальных денежных расчетов (до 9,99 млн. Долл. США) могут уместиться в a DECIMAL(9, 2), который требует всего пять байтов. Вы можете сохранить размер, меньше беспокоиться об ошибках округления и сделать свой код более переносимым.
Хотя @JonofAllTrades верен, вы также можете получить целочисленную производительность, просто используя целое число, содержащее копейки или центы, и сохранить дополнительный байт, который кодирует позицию десятичной точки и который должен быть проверен при добавлении десятичных знаков вместе.
dsz
«Таким образом, совершенно« безопасно »и целесообразно использовать ДЕНЬГИ, когда вы имеете дело с ДЕНЬГАМИ, и использовать их в соответствии с математическими правилами, которые следует» -> однако, смотрите также ответ Анона: «Все опасно, если вы этого не сделаете знаю, что ты делаешь ". Вы никогда не сможете предсказать, как люди в конечном итоге будут запрашивать создаваемую вами систему, чтобы избежать возможности неправильного использования, когда это возможно. Мельчайший прирост в памяти не стоит ИМХО.
Натан Гриффитс
1
Попробуйте сохранить значение биткойна. Он имеет 8 знаков после запятой
Panagiotis Kanavos
14

Мы только что столкнулись с очень похожей проблемой, и теперь я очень +1 за то, что никогда не использую деньги, кроме как в презентации на высшем уровне. У нас есть несколько таблиц (фактически, ваучер продаж и счет-фактура продаж), каждая из которых содержит одно или несколько полей «Деньги» по историческим причинам, и нам необходимо выполнить пропорциональный расчет, чтобы определить, какая часть общего налога на счет-фактуру относится к каждому линия на ваучер продаж. Наш расчет

vat proportion = total invoice vat x (voucher line value / total invoice value)

Это приводит к реальному расчету денег / денег, который вызывает ошибки масштаба в части деления, которая затем умножается до неправильной пропорции НДС. Когда эти значения впоследствии добавляются, мы получаем сумму пропорций НДС, которые не суммируются с общей стоимостью счета. Если бы любое из значений в скобках было десятичным (я собираюсь привести одно из них как таковое), пропорция НДС была бы правильной.

Когда скобки изначально отсутствовали, это работало, я думаю, из-за больших значений, это эффективно имитировало более высокую шкалу. Мы добавили скобки, потому что сначала выполнялось умножение, которое в некоторых редких случаях сказывалось на точности, доступной для вычисления, но теперь это стало причиной гораздо более распространенной ошибки.

Kaideejee
источник
8
Но это происходит только потому, что невежественный разработчик игнорировал правила расчета НДС и задокументированные ограничения точности денег.
TomTom
1
@TomTom, но вы указываете на возможность неправильного использования этого типа данных - аргумент в пользу того, чтобы вообще не использовать его.
Натан Гриффитс
@ Натан Нет. Я отмечаю, что аргумент, приведенный в качестве причины, чтобы никогда не использовать его, в основном некомпетентный разработчик, поэтому аргумент является поддельным.
TomTom
1
@TomTom, к сожалению, есть много некомпетентных разработчиков (а также много замечательных) и для меня, если я не смогу гарантировать, что эти данные будут запрашиваться в будущем, и никто никогда не собирался делать ошибки, описанные здесь. Лучше ошибиться на стороне осторожности и использовать десятичный тип. Тем не менее, прочитав все эти ответы, я вижу, что есть некоторые конкретные случаи использования, когда деньги были бы оптимальным типом использования, я бы просто не использовал их, если бы не было очень хорошего варианта использования для них (например, столбец будет всегда агрегировать по сумме, загружая большие объемы финансовых данных).
Натан Гриффитс
@TomTom это не просто ограничения точности. Внутреннее представительство также может вызвать проблемы. Деньги - это удобный способ ловить невежественных разработчиков, а не тот тип, которым разработчики злоупотребляют. Пример НДС, независимо от правил его расчета, явно должен отпугивать невежественных разработчиков, когда они применяют специфическое к общему.
Джерард ONeill
12

В качестве контрапункта общей направленности других ответов. Смотрите много преимуществ денег ... Тип данных! в руководстве SQLCAT по реляционному движку

В частности, я бы отметил следующее

Работая над реализацией клиента, мы нашли несколько интересных показателей производительности, касающихся типа данных money. Например, когда службам Analysis Services был задан тип данных валюты (от двойного) для соответствия типу данных денег SQL Server, скорость обработки данных увеличилась на 13% (строк / сек). Чтобы повысить производительность служб SQL Server Integration Services (SSIS) и загрузить 1,18 ТБ менее чем за тридцать минут, как отмечалось в SSIS 2008 - мировой рекорд производительности ETL, было отмечено, что изменение четырех десятичных (9,2) столбцов с размером 5 байт в таблице TPC-H LINEITEM к деньгам (8 байт) повысили скорость массовой вставки на 20% ... Причина повышения производительности заключается в протоколе табличного потока данных (TDS) SQL Server, который имеет ключевой принцип проектирования для передачи данных в компактной двоичной форме и как можно ближе к внутреннему формату хранения SQL Server. Опытным путем это наблюдалось во время SSIS 2008 - мирового теста производительности ETL с использованием Kernrate; Протокол значительно упал, когда тип данных был переведен на деньги с десятичной. Это делает передачу данных максимально эффективной. Сложный тип данных требует дополнительного анализа и циклов ЦП для обработки, чем тип с фиксированной шириной.

Таким образом, ответ на вопрос «это зависит». Вы должны быть более осторожными с некоторыми арифметическими операциями, чтобы сохранить точность, но вы можете обнаружить, что соображения производительности делают это стоящим.

Мартин Смит
источник
Как вы будете хранить биткойны ?
Панагиотис Канавос
@PanagiotisKanavos - я понятия не имею. Я никогда не изучал биткойны и практически ничего о них не знаю!
Мартин Смит
6

Я хочу дать другое представление о ДЕНЬГАХ и NUMERICAL, в значительной степени основываясь на своем собственном опыте и опыте ... Моя точка зрения здесь - ДЕНЬГИ, потому что я работал с ним в течение длительного времени и никогда не использовал NUMERICAL. ,

ДЕНЬГИ Pro:

  • Родной тип данных . Он использует собственный тип данных ( целое число ), такой же, как регистр ЦП (32 или 64 бита), поэтому для вычисления не нужны лишние издержки, поэтому он меньше и быстрее ... MONEY требуется 8 байтов и NUMERICAL (19, 4 ) требуется 9 байт (на 12,5% больше) ...

    ДЕНЬГИ быстрее, если их использовать, как предполагалось (как деньги). Как быстро? Мой простой SUMтест на 1 млн. Данных показывает, что ДЕНЬГИ составляют 275 мс, а ЧИСЛЕННЫЕ 517 мс ... Это почти вдвое быстрее ... Почему тест СУММ? Смотрите следующую Pro точку

  • Лучшее за деньги . ДЕНЬГИ лучше всего подходят для хранения денег и выполнения операций, например, в бухгалтерском учете. Один отчет может выполнить миллионы сложений (SUM) и несколько умножений после выполнения операции SUM. Для очень больших бухгалтерских приложений это почти в два раза быстрее , и это чрезвычайно важно ...
  • Низкая точность денег . Деньги в реальной жизни не должны быть очень точными. Я имею в виду, что многие люди могут заботиться о 1 центе США, но как насчет 0,01 цента США? На самом деле, в моей стране банки больше не заботятся о центах (цифры после десятичной запятой); Я не знаю о банке США или другой стране ...

ДЕНЬГИ Con:

  • Ограниченная точность . ДЕНЬГИ имеют только четыре цифры (после запятой), поэтому их необходимо преобразовать перед выполнением таких операций, как деление ... Но, опять moneyже, не нужно быть таким точным, и их следует использовать в качестве денег, а не просто число...

Но ... Большой, но здесь даже ваше приложение связано с реальными деньгами, но не используйте его во многих операциях SUM, например, в бухгалтерском учете. Если вместо этого вы используете множество делений и умножений, вам не следует использовать ДЕНЬГИ ...

Сусило
источник
1
Если вы хотите сказать, что деньги быстрее десятичных, вам нужно сообщить нам такие вещи, как то, что rdbms, на каком оборудовании, на какой ОС, с какими конкретными данными, на каком конкретном запросе вы говорите. Кроме того, если это не ПОЛНОСТЬЮ, я не буду делать с ним никаких финансовых операций, потому что налоговый инспектор будет весьма недоволен возвращением неверных цифр. Вы заботитесь о тысячных центах, например, если имеете дело с валютой США. Если деньги этого не делают, их нельзя использовать.
Хакон Лотвейт
3
@ HaakonLøtveit весь этот поток вопросов и ответов о типе данных SQL Server «деньги», поэтому я не думаю, что им нужно указывать это в ответе. Деньги могут быть быстрее использовать, чем десятичные в некоторых обстоятельствах (например, загрузка данных), подробнее см. Ответ Мартина Смита. Я согласен с большинством этого ответа в том, что есть определенные варианты использования, которые могут сделать Деньги более эффективным выбором, чем десятичный, однако, если нет очень убедительных аргументов в пользу его использования, я думаю, что этого следует избегать.
Натан Гриффитс
1
Биткойн имеет 8 знаков после запятой. Вы даже не можете хранить это в moneyстолбце
Panagiotis Kanavos
4

Все предыдущие посты приносят действительные баллы, но некоторые не дают точного ответа на вопрос.

Вопрос в том, почему кто-то предпочитает деньги, если мы уже знаем, что это менее точный тип данных и может привести к ошибкам при использовании в сложных вычислениях?

Вы используете деньги, когда не будете делать сложные вычисления и можете обменять эту точность на другие нужды.

Например, когда вам не нужно делать эти вычисления, и вам нужно импортировать данные из допустимых текстовых строк валюты. Это автоматическое преобразование работает только с типом данных MONEY:

SELECT CONVERT(MONEY, '$1,000.68')

Я знаю, что вы можете сделать свою собственную процедуру импорта. Но иногда вы не хотите воссоздавать подпрограмму импорта со специфическими для мира форматами локали.

Другой пример, когда вам не нужно делать эти вычисления (вам нужно просто сохранить значение) и вам нужно сохранить 1 байт (деньги занимают 8 байт, а десятичное число (19,4) - 9 байт). В некоторых приложениях (быстрый процессор, большой объем оперативной памяти, медленный ввод-вывод), например, просто чтение огромного количества данных, это также может быть быстрее.

Вебер К.
источник
2

Вы не должны использовать деньги, когда вам нужно сделать умножения / деления на значение. Деньги хранятся так же, как целое число, тогда как десятичная дробь хранится в виде десятичной точки и десятичных цифр. Это означает, что в большинстве случаев деньги будут снижать точность, тогда как десятичная дробь будет делать это только при преобразовании обратно в исходный масштаб. Деньги - это фиксированная точка, поэтому ее масштаб не изменяется при расчетах. Однако, поскольку это фиксированная точка, когда она печатается в виде десятичной строки (в отличие от фиксированной позиции в строке с основанием 2), значения до масштаба 4 представляются точно. Таким образом, для сложения и вычитания деньги в порядке.

Десятичная дробь представлена ​​в основании 10 внутренне, и, таким образом, положение десятичной точки также основано на числе 10. Что делает его дробную часть точно отражающей его стоимость, точно так же как с деньгами. Разница в том, что промежуточные значения десятичной дроби могут поддерживать точность до 38 цифр.

Для числа с плавающей запятой значение сохраняется в двоичном виде, как если бы оно было целым числом, а позиция десятичной (или двоичной, ага) точки относительно битов, представляющих число. Поскольку это двоичная десятичная точка, базовые числа 10 теряют точность сразу после десятичной точки. 1/5 или 0,2 не могут быть представлены именно таким образом. Ни деньги, ни десятичные числа не страдают от этого ограничения.

Достаточно просто преобразовать деньги в десятичную, выполнить вычисления, а затем сохранить полученное значение обратно в денежное поле или переменную.

От моего POV я хочу, чтобы вещи, которые случаются с числами, просто происходили без необходимости слишком много думать о них. Если все вычисления будут преобразованы в десятичную, то для меня я бы просто хотел использовать десятичную. Я бы сохранил поле денег для отображения.

По размерам я не вижу достаточной разницы, чтобы передумать. Деньги занимают 4 - 8 байтов, тогда как десятичные могут быть 5, 9, 13 и 17. 9 байтов могут охватывать весь диапазон, который могут 8 байтов денег. По индексу (сравнение и поиск должны быть сопоставимы).

Жерар ОНЕЙЛ
источник
Спасибо за Upvote. Я смотрю на это и, в то время как я получаю то, что я пытался сказать, я также вижу, что это очень сбивает с толку. Возможно, я перепишу это позже с некоторыми битами против десятичных примеров.
Джерард ONeill
2

Я нашел причину использования десятичной над деньгами в точности предмета.

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

DecimalResult> 1.000000

MoneyResult> 0,9999

FloatResult> 1

Просто проверьте это и примите решение.

Qmaster
источник
2
Мы бы очень хотели услышать (прочитайте, то есть) ваше заключение.
Питер Мортенсен
@PeterMortensen Я думаю, что если я хочу иметь полноту и точность между типами Money и Decimal, мое решение должно быть Decimal.
QMaster
1
Подумайте об обновлении вашего ответа фактическим результатом выше. Тогда ваш вывод будет сразу очевиден для любого читающего :-)
Agreax
1
@Ageax Результат добавлен в ответ.
QMaster,
1

Я только что увидел эту запись в блоге: Деньги против десятичного в SQL Server .

Который в основном говорит, что у денег есть проблема точности ...

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 частей для расчета, но этот пример действительно имеет некоторые ограничения.

Harsha
источник
15
Это не «проблема», а «согласно спецификациям»: « Типы данных « moneyи » smallmoneyс точностью до десятитысячной доли денежных единиц, которые они представляют». как сказано в msdn.microsoft.com/en-us/library/ms179882.aspx, поэтому любой, кто говорит «это мусор», не знает, о чем говорит.
Albireo