Должны ли вы выбирать типы данных MONEY или DECIMAL (x, y) в SQL Server?
Мне любопытно, существует ли реальная разница между типом данных money
и чем-то вроде decimal(19,4)
(что, как я полагаю, использует внутренние средства).
Я знаю, что money
специфичны для SQL Server. Я хочу знать, есть ли веские причины выбирать один за другим; большинство образцов SQL Server (например, база данных AdventureWorks) используют money
а не decimal
для таких вещей, как информация о ценах.
Должен ли я просто продолжать использовать тип данных денег, или есть ли преимущество использования десятичного числа? Денег меньше символов для ввода, но это не допустимая причина :)
Ответы
Ответ 1
Никогда не следует использовать деньги. Это не точно, и это чистый мусор; всегда используйте десятичную/цифровую.
Запустите это, чтобы понять, что я имею в виду:
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
Ответ 2
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 десятичных цифр, и вы убедитесь, что ваши скаляры, которые не представляют собой деньги, - это decimal
s.
Ответ 3
Все опасно, если вы не знаете, что делаете
Даже высокоточные десятичные типы не могут сохранить день:
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
является визуальным пухом, точно так же, как тире в yyyy-mm-dd Дата. SQL фактически не сохраняет их внутри.
Относительно decimal
vs money
выберите все, что подходит для ваших нужд. Типы money
существуют, потому что хранение учетных значений как целочисленных кратных 1/10000-й единицы очень распространено. Кроме того, если вы имеете дело с фактическими деньгами и расчетами, помимо простого сложения и вычитания, вы не должны делать это на уровне базы данных! Сделайте это на уровне приложения с помощью библиотеки, поддерживающей Округление Banker (IEEE 754)
Ответ 4
Я понимаю, что WayneM заявила, что знает, что деньги специфичны для SQL Server. Тем не менее, он спрашивает, есть ли какие-либо причины использовать деньги за десятичные или наоборот, и я думаю, что одна очевидная причина все еще должна быть указана, и что использование десятичного означает, что нужно меньше беспокоиться о том, что вам когда-либо придется менять свою СУБД - что может случиться.
Сделайте ваши системы максимально гибкими!
Ответ 5
Ну, мне нравится MONEY
! Это байт дешевле, чем DECIMAL
, и вычисления выполняются быстрее, потому что (под обложками) операции сложения и вычитания являются по существу целыми операциями. @SQLMenace example &mdash, который является отличным предупреждением для не знающего &mdash, может быть одинаково применим к INT
egers, где результат будет равен нулю. Но это не значит, что вы не должны использовать целые числа &mdash, где это необходимо.
Итак, он отлично "безопасен" и подходит для использования MONEY
, когда вы имеете дело с MONEY
и используете его в соответствии с математическими правилами, которые он следует (такими же, как INT
eger).
Было бы лучше, если бы SQL Server способствовал разделению и умножению MONEY
на DECIMAL
(или FLOAT
s?) — возможно, но они не решили это сделать; и они не решили продвигать INT
egers до FLOAT
при их делении.
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
усечено — то же самое, что и целое число.)
Ответ 6
В качестве противопоказания общей направленности других ответов. См. "Много преимуществ денег... Тип данных! в Руководство SQLCAT для реляционного движка
В частности, я хотел бы указать следующее
Работая над реализацией клиента, мы обнаружили несколько интересных которые относятся к типу денежных данных. Например, когда Служба Analysis Services была настроена на тип данных валюты (от двойного) до соответствуют типу данных данных SQL Server, было улучшено 13% скорость обработки (строки/сек). Чтобы получить более высокую производительность в SQL Службы интеграции с сервером (SSIS) загружают 1,18 ТБ менее чем за тридцать минут, как отмечено в SSIS 2008 - мировой рекорд ETL, это было заметил, что изменение четырех десятичных (9,2) столбцов с размером 5 байтов в таблице TPC-H LINEITEM на деньги (8 байт) улучшена объемная скорость вставки на 20%... Причина повышения производительности связана с протоколом табличного потока данных SQL Server (TDS), который имеет ключевой принцип проектирования для передачи данных в компактной двоичной форме и как можно ближе к внутреннему хранилищу формат SQL Server. Эмпирически это наблюдалось во время SSIS 2008 - мировой рекорд производительности ETL с использованием Kernrate; протокол значительно снизился, когда тип данных был переключен на деньги с десятичной точки. Это делает передача данных как можно более эффективной. Для сложного типа данных требуется дополнительный синтаксический анализ и циклы CPU для обработки, чем тип фиксированной ширины.
Итак, ответ на вопрос "это зависит". Вам нужно быть более осторожным с определенными арифметическими операциями, чтобы сохранить точность, но вы можете обнаружить, что соображения производительности делают это стоящим.
Ответ 7
Мы столкнулись с очень похожими проблемами, и теперь я очень люблю +1, чтобы никогда не использовать деньги, кроме презентации на высшем уровне. У нас есть несколько таблиц (фактически ваучер на продажу и счет-фактура), каждый из которых содержит по одному или нескольким денежным полям по историческим причинам, и нам нужно выполнить пропорциональный расчет, чтобы определить, какая часть общего налога на накладную имеет отношение к каждому лайн на ваучере продажи. Наш расчет
vat proportion = total invoice vat x (voucher line value / total invoice value)
Это приводит к расчету реальных денег/денег, который вызывает ошибки шкалы в части деления, которая затем умножается на некорректную пропорцию вата. Когда эти значения впоследствии добавляются, мы получаем сумму пропорций вата, которые не суммируются с общей стоимостью счета. Если бы одно из значений в скобках было десятичным (я собираюсь бросить один из них как таковой), пропорция vat будет правильной.
Когда скобки не были изначально, это использовалось для работы, я думаю, из-за более значительных значений он эффективно имитировал более высокий масштаб. Мы добавили скобки, потому что сначала выполняли умножение, что в некоторых редких случаях приводило к точности, доступной для расчета, но теперь это вызвало гораздо более распространенную ошибку.
Ответ 8
Я хочу дать другое представление о MONEY vs. NUMERICAL, в значительной степени основанный на моем собственном опыте и опыте... Моя точка зрения здесь - ДЕНЬГИ, потому что я работал с ней в течение долгого времени и никогда не использовал ЧИСЛЕННЫЙ много..,
MONEY Pro:
-
Собственный тип данных. Он использует собственный тип данных (целочисленный) как тот же, что и регистр CPU (32 или 64 бит), поэтому для вычисления не нужны лишние накладные расходы, поэтому он меньше и быстрее... Денежные средства нуждаются в 8 байтах и NUMERICAL (19, 4 ) требует 9 байтов (на 12,5% больше)...
ДЕНЬГИ быстрее, пока она используется для того, чтобы она была (как деньги). Как быстро? Мой простой тест SUM
на 1 миллион данных показывает, что MONEY составляет 275 мс, а NUMERIC 517 мс... Это почти в два раза быстрее... Почему тест SUM? См. Следующий пункт Pro
- Лучше всего для денег. ДЕНЬГИ лучше всего хранить деньги и делать операции, например, в сфере бухгалтерского учета. Один отчет может запускать миллионы дополнений (SUM) и несколько умножений после выполнения операции SUM. Для очень больших учетных приложений это почти в два раза быстрее, и это чрезвычайно важно...
- Низкая точность денег. Деньги в реальной жизни не обязательно должны быть очень точными. Я имею в виду, что многие люди могут заботиться о 1 центах, но как насчет 0,01% доллара США? Фактически, в моей стране банки больше не заботятся о центах (цифра после десятичной запятой); Я не знаю об американском банке или другой стране...
MONEY Con:
- Ограниченная точность. ДЕНЬГИ имеет только четыре цифры (после запятой), поэтому ее нужно преобразовать, прежде чем делать операции, такие как деление... Но опять же
money
не должны быть настолько точными и предназначены для использования как деньги, а не только число...
Но... Большой, но здесь даже ваше приложение связано с реальными деньгами, но не используйте его во многих операциях СУМ, как в бухгалтерии. Если вы используете множество делений и умножений, вместо этого вы не должны использовать ДЕНЬГИ...
Ответ 9
Вы не должны использовать деньги, когда вам нужно делать умножения/деления на значение. Деньги хранятся таким же образом, как и целое число, тогда как десятичное значение сохраняется как десятичная точка и десятичные цифры. Это означает, что в большинстве случаев деньги будут снижать точность, а десятичная - только при преобразовании обратно в исходный масштаб. Деньги - фиксированная точка, поэтому ее масштаб не изменяется во время расчетов. Однако, поскольку это фиксированная точка, когда она печатается как десятичная строка (в отличие от фиксированной позиции в строке 2), значения до шкалы 4 представлены точно. Итак, для сложения и вычитания деньги в порядке.
Десятичное число представлено в базе 10 внутренне, и, следовательно, позиция десятичной точки также основана на базовом значении 10. Который делает его дробную часть точно представлять ее ценность, как деньги. Разница заключается в том, что промежуточные значения десятичного числа могут поддерживать точность до 38 цифр.
С номером с плавающей запятой значение сохраняется в двоичном виде, как если бы оно было целым числом, а позиция десятичной (или двоичной, гем) точки относительно битов, представляющих число. Поскольку это двоичная десятичная точка, базовые 10 чисел теряют точность сразу после десятичной точки. 1/5, или 0.2, не могут быть представлены точно таким образом. Эти деньги не ограничены ни деньгами, ни десятичными знаками.
Достаточно легко конвертировать деньги в десятичные числа, выполнять вычисления, а затем сохранять полученное значение обратно в денежное поле или переменную.
Из моего POV я хочу, чтобы вещи, которые случаются с числами, просто случались, не дав им слишком много размышлений. Если все вычисления будут преобразованы в десятичные, то для меня я просто хочу использовать десятичное число. Я бы сохранил денежное поле для показа.
По размеру я не вижу достаточной разницы, чтобы изменить свое мнение. Деньги берут 4 - 8 байт, тогда как десятичный может быть 5, 9, 13 и 17. 9 байтов могут охватывать весь диапазон, который может использовать 8 байтов денег. Индексный (сравнение и поиск должны быть сопоставимы).
Ответ 10
Все предыдущие посты приносят действительные баллы, но некоторые не дают точного ответа на вопрос.
Вопрос в том, почему кто-то предпочитает деньги, если мы уже знаем, что это менее точный тип данных и может привести к ошибкам при использовании в сложных вычислениях?
Вы используете деньги, когда не будете делать сложные вычисления и можете обменять эту точность на другие нужды.
Например, когда вам не нужно делать эти вычисления, и вам нужно импортировать данные из допустимых текстовых строк валюты. Это автоматическое преобразование работает только с типом данных MONEY:
SELECT CONVERT(MONEY, '$1,000.68')
Я знаю, что вы можете сделать свою собственную процедуру импорта. Но иногда вы не хотите воссоздавать процедуру импорта в форматах, специфичных для разных стран.
Другой пример, когда вам не нужно делать эти вычисления (вам нужно просто сохранить значение) и вам нужно сохранить 1 байт (деньги занимают 8 байт, а десятичное число (19,4) - 9 байт). В некоторых приложениях (быстрый процессор, большой объем оперативной памяти, медленный ввод-вывод), например, просто чтение огромного количества данных, это также может быть быстрее.
Ответ 11
Я только что видел эту запись в блоге: Деньги против Десятичного числа в 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 частей для расчета, но этот пример действительно обнажает некоторые ограничения.
Ответ 12
Я нашел причину использования десятичной запятой в деньгах в точности.
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
Просто проверь это и прими решение.