Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Форматирование decimal(31, 15) в строку на стороне сервера / 9 сообщений из 9, страница 1 из 1
15.10.2018, 08:10
    #39717382
WinterGraveyard
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Форматирование decimal(31, 15) в строку на стороне сервера
Ситуация: в клиентской программе на дельфи (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-й.
Была написана вот такая функция:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
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


Вроде бы работает вполне нормально, но, может, здесь можно что-то подкрутить в плане лаконичности, быстродействия, итд?
...
Рейтинг: 0 / 0
15.10.2018, 14:03
    #39717635
iiyama
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Форматирование decimal(31, 15) в строку на стороне сервера
WinterGraveyard,
Прошу прощения за небольшой оффтопик(тк без анализа ф-ции),
не проще ли просто 2-мя int-ами отдать (целая и дробная часть) и форматировать все же на клиенте?
...
Рейтинг: 0 / 0
15.10.2018, 15:22
    #39717697
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Форматирование decimal(31, 15) в строку на стороне сервера
iiyamaWinterGraveyard,
Прошу прощения за небольшой оффтопик(тк без анализа ф-ции),
не проще ли просто 2-мя int-ами отдать (целая и дробная часть) и форматировать все же на клиенте?Простым intом не получится - у него не более 10 знаков
...
Рейтинг: 0 / 0
15.10.2018, 16:10
    #39717731
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Форматирование decimal(31, 15) в строку на стороне сервера
WinterGraveyard,

я бы написал CLR функцию для таких целей.
...
Рейтинг: 0 / 0
15.10.2018, 16:12
    #39717733
Shakill
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Форматирование decimal(31, 15) в строку на стороне сервера
WinterGraveyardформатировать decimal(31,15) в varchar на сервере. Требования: 15 знаков после запятой, разделитель дробной и целой частей запятая, разделитель разрядов целой части пробел. Сервер - 2005-й.

если вдруг окажется сервер 2012 :)
Код: sql
1.
2.
declare @d decimal(31,15) = -1234567890123456.123456789012345
select format(@d, 'n15', 'ru')  
...
Рейтинг: 0 / 0
16.10.2018, 04:50
    #39717896
Massa52
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Форматирование decimal(31, 15) в строку на стороне сервера
WinterGraveyard,
Код: sql
1.
2.
declare @d decimal(31,15) = -1234567890123456.543210987654321
select cast(@d AS bigint), cast((@d - cast(@d AS bigint)) * 1000000000000000 AS bigint) 
...
Рейтинг: 0 / 0
16.10.2018, 08:07
    #39717912
WinterGraveyard
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Форматирование decimal(31, 15) в строку на стороне сервера
Massa52WinterGraveyard,
Код: sql
1.
2.
declare @d decimal(31,15) = -1234567890123456.543210987654321
select cast(@d AS bigint), cast((@d - cast(@d AS bigint)) * 1000000000000000 AS bigint) 


Нет, спасибо, передавать клиенту два значения вместо одного, и потом собирать из них одно в средствах отображения (DevExpress QuantunGrid/FastReports) - это намного больше возни, чем отформатировать значение на сервере (к тому же выборки в контексте данной задачи небольшие, и вряд ли такие преобразования сильно нагрузят сервер).
Владислав КолосовWinterGraveyard,
я бы написал CLR функцию для таких целей.
Отпадает - по каким-то причинам администраторы не хотят возиться с хостингом CLR-сборок на сервере.
Shakillесли вдруг окажется сервер 2012 :)
Да, спасибо, я в курсе, но есть только то, что есть. И насколько я понимаю вот это
авторFORMAT relies on the presence of the .NET Framework Common Language Runtime (CLR).
эта функция и является оберткой над дотнетовским форматированием (и использует дотнетовские форматы).
...
Рейтинг: 0 / 0
16.10.2018, 08:34
    #39717915
PizzaPizza
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Форматирование decimal(31, 15) в строку на стороне сервера
WinterGraveyard,

Практический вопрос: судя по тому, что вы разделяете разряды пробелом, это число требуется просто для отображения? Может проще его передавать строкой в клиент и там уже как строку форматировать? Сдается мне на Дельфи это гораздо короче получится (не уверен).
...
Рейтинг: 0 / 0
16.10.2018, 08:50
    #39717918
Massa52
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Форматирование decimal(31, 15) в строку на стороне сервера
WinterGraveyard,
Кстати - ваша функция не работает для значения -1234567890123456.543210987654321
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Форматирование decimal(31, 15) в строку на стороне сервера / 9 сообщений из 9, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]