Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
WinterGraveyard Member Откуда: Сообщений: 75 |
Ситуация: в клиентской программе на дельфи (RAD Studio 2010) нужно отображать значения типа decimal(31, 15), полностью отображая все знаки после запятой (все 15). Как выяснилось, сделать это, передавая на клиент значения как есть (именно decimal(31,15)) невозможно: при отключенной опции EnableBCD значения передаются как double, и ряд значений при заданной маске отображения 15 знаков приобретают в дробной части хвост, которого на самом деле нет - видимо, это связано с потерей точности при прееобразовании в double по IEEE-754. Если включить опцию EnableBCD, значения передаются как binary-coded decimal (собственно, BCD), но обычный BCD (TBCDField) производит округление до формата currency (до 3 знаков), что неприемлемо. А значения типа TFMTBCD (TFMTBСDField), где округление не производится, используемая версия библиотеки доступа к данным (DevArt SDAC) не поддерживает. Ввиду всего вышеизложенного было принято решение форматировать decimal(31,15) в varchar на сервере. Требования: 15 знаков после запятой, разделитель дробной и целой частей запятая, разделитель разрядов целой части пробел. Сервер - 2005-й. Была написана вот такая функция: CREATE FUNCTION [DBO].[UF_FORMAT_DECIMAL](@D DECIMAL(31,15)) RETURNS TABLE AS RETURN WITH CTE AS ( SELECT @D N ) SELECT F1.Z+LTRIM(F3.D)+F2.A RESULT FROM CTE E CROSS APPLY ( SELECT CASE WHEN CONVERT(VARCHAR, E.N) LIKE '-%' THEN '-' ELSE '' END, SUBSTRING( REPLACE(CONVERT(VARCHAR, E.N), '.', ','), CASE WHEN CONVERT(VARCHAR, E.N) LIKE '-%' THEN 2 ELSE 1 END, LEN(CONVERT(VARCHAR, N)) ) ) F1(Z,S) CROSS APPLY ( SELECT SUBSTRING(F1.S, 1, CHARINDEX(',', F1.S)-1), SUBSTRING(F1.S, CHARINDEX(',', F1.S), LEN(F1.S)) ) F2(B, A) CROSS APPLY ( SELECT SUBSTRING(F2.B, LEN(F2.B)-17, 3) +' '+SUBSTRING(F2.B, LEN(F2.B)-14, 3) +' '+SUBSTRING(F2.B, LEN(F2.B)-11, 3) +' '+SUBSTRING(F2.B, LEN(F2.B)-8, 3) +' '+SUBSTRING(F2.B, LEN(F2.B)-5, 3) +' '+SUBSTRING(F2.B, LEN(F2.B)-2, 3) ) F3(D) GO Вроде бы работает вполне нормально, но, может, здесь можно что-то подкрутить в плане лаконичности, быстродействия, итд? |
15 окт 18, 08:10 [21703842] Ответить | Цитировать Сообщить модератору |
iiyama Member Откуда: Сообщений: 642 |
WinterGraveyard, Прошу прощения за небольшой оффтопик(тк без анализа ф-ции), не проще ли просто 2-мя int-ами отдать (целая и дробная часть) и форматировать все же на клиенте? |
15 окт 18, 14:03 [21704184] Ответить | Цитировать Сообщить модератору |
iap Member Откуда: Москва Сообщений: 47063 |
|
||
15 окт 18, 15:22 [21704273] Ответить | Цитировать Сообщить модератору |
Владислав Колосов Member Откуда: Сообщений: 8485 |
WinterGraveyard, я бы написал CLR функцию для таких целей. |
15 окт 18, 16:10 [21704321] Ответить | Цитировать Сообщить модератору |
Shakill Member Откуда: мск Сообщений: 1882 |
если вдруг окажется сервер 2012 :) declare @d decimal(31,15) = -1234567890123456.123456789012345 select format(@d, 'n15', 'ru') |
||
15 окт 18, 16:12 [21704323] Ответить | Цитировать Сообщить модератору |
Massa52 Member Откуда: Сообщений: 382 |
WinterGraveyard,declare @d decimal(31,15) = -1234567890123456.543210987654321 select cast(@d AS bigint), cast((@d - cast(@d AS bigint)) * 1000000000000000 AS bigint) |
16 окт 18, 04:50 [21704679] Ответить | Цитировать Сообщить модератору |
WinterGraveyard Member Откуда: Сообщений: 75 |
Нет, спасибо, передавать клиенту два значения вместо одного, и потом собирать из них одно в средствах отображения (DevExpress QuantunGrid/FastReports) - это намного больше возни, чем отформатировать значение на сервере (к тому же выборки в контексте данной задачи небольшие, и вряд ли такие преобразования сильно нагрузят сервер).
Отпадает - по каким-то причинам администраторы не хотят возиться с хостингом CLR-сборок на сервере.
Да, спасибо, я в курсе, но есть только то, что есть. И насколько я понимаю вот это
эта функция и является оберткой над дотнетовским форматированием (и использует дотнетовские форматы). |
||||||||
16 окт 18, 08:07 [21704718] Ответить | Цитировать Сообщить модератору |
PizzaPizza Member Откуда: Сообщений: 422 |
WinterGraveyard, Практический вопрос: судя по тому, что вы разделяете разряды пробелом, это число требуется просто для отображения? Может проще его передавать строкой в клиент и там уже как строку форматировать? Сдается мне на Дельфи это гораздо короче получится (не уверен). |
16 окт 18, 08:34 [21704732] Ответить | Цитировать Сообщить модератору |
Massa52 Member Откуда: Сообщений: 382 |
WinterGraveyard, Кстати - ваша функция не работает для значения -1234567890123456.543210987654321 |
16 окт 18, 08:50 [21704742] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |