Как округлить столбец, определенный как Float на INSERT и UPDATE в SQL Server 2005 - PullRequest
0 голосов
/ 05 февраля 2009

Я работаю над базой данных, которая использует тип данных Float для хранения значений, которые должны быть только 2 десятичных знака (доллары и центы). Использование Float, кажется, работает нормально, пока человек, обновляющий столбец Float, делает ROUND. Конечно, это не всегда случается, и тогда, когда СУММА сделана, это всегда отклоняется от нескольких пенсов от того, что отображено, потому что дисплей отформатирован, чтобы показать только 2 десятичных положения. В этой базе данных есть сотни таблиц, использующих Float, и было бы полезно иметь возможность автоматически РАУНДИТЬ столбцы с плавающей точкой.

Можно ли это сделать?

Можно ли использовать TRIGGER на INSERT и UPDATE, чтобы сделать ROUND на столбце?

Если бы это было возможно, вы могли бы показать, как вы будете кодировать TRIGGER, и вы бы порекомендовали его?

Есть еще идеи?

Мы используем SQL Server 2005.

Это сообщение, в котором задается вопрос Использовать число с плавающей запятой или десятичное число для учетной суммы в долларах для приложения бухгалтерского учета? и мне нравится ответ, в котором указано

«Вам действительно следует рассмотреть возможность использования какого-либо типа пакета с фиксированной точкой / произвольной точности (например, java BigNum, десятичный модуль python), в противном случае вы попадете в мир боли ».

Я чувствую боль!

Ответы [ 3 ]

3 голосов
/ 05 февраля 2009

Если вы контролируете систему, можете ли вы использовать тип данных DECIMAL / MONEY / NUMERIC вместо FLOAT?

В конце концов, это точка вопроса, на которую вы ссылались.

Если нет, и, как и многие из нас, вы вынуждены жить в этом мире боли, ваше предложение триггера сработает. Я бы предпочел, однако, контролировать это по-другому ...
- Не разрешать приложениям или пользователям прямой доступ для записи в таблицы
- Принудительный доступ через SP

Я также видел систему, в которой доступ на запись предоставляется одной (входной / удерживающей) таблице. Эта таблица затем имеет триггер для копирования (и форматирования / проверки) данных в реальную таблицу.

3 голосов
/ 05 февраля 2009

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

Кроме того, вы можете сделать одноразовое исправление, например:

update tbl set column = round(column * 100) / 100

Синтаксис может быть не идеальным, но вы должны понять.

Но я не уверен, что понимаю ваше замечание "за несколько копеек". Вам нужно было бы суммировать довольно большое число с плавающей точкой для накопления ошибок до 0,01. Какое определение столбца вы используете?

Конечно, одно из определений десятичного столбца денежного типа было бы лучше для идеальной точности, но вы можете потерять переносимость между СУБД.

1 голос
/ 05 февраля 2009

Я не думаю, что вы можете получить именно то, что вы хотите, округляя. Округление числа с плавающей точкой не будет работать точно и надежно: что бы вы ни делали, вы будете пытаться применить десятичное округление к двоичному числу, и это не будет точным для чего-либо, кроме степени 2.

Вы можете получить точные сохраненные в базе данных десятичные представления произвольных субцелых величин, используя десятичный тип данных, специально разработанный для этой цели. Эти типы данных обычно используют некоторую форму упакованного десятичного хранилища (так менее эффективно, чем двоичное), где, например, 2009 хранится как 0x2009.

Что произойдет, если вы используете функцию CONVERT ? Вы пытались сделать запрос, используя что-то вроде этого?

CONVERT(money, your_float_column)

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

Тогда я выслеживал и наказывал тех, кто считал, что хранить деньги в поплавке - хорошая идея ...

...