Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 String.Format отказывается форматировать по заданному формату  [new]
sasharzv
Member

Откуда:
Сообщений: 13
Потребовалось произвольное форматирование различных типов данных в запросах.
Написал CLR функцию:
[Microsoft.SqlServer.Server.SqlFunction(Name = "f_FormatString", IsDeterministic = true)]
public static SqlString fe_FormatString(SqlString InStringFormat, System.Object InObj1, System.Object InObj2)
{
    try
    {
        return new SqlString(String.Format(InStringFormat.ToString(), InObj1, InObj2));
    }
    catch
    {
    }
    return new SqlString();
}

Подключил в MSSQL 2005:
CREATE FUNCTION dbo.f_FormatString(@InFormatString nvarchar(4000), @InObj1 sql_variant, @InObj2 sql_variant)
 RETURNS nvarchar(4000)
 WITH EXECUTE AS CALLER AS EXTERNAL NAME lib_name.UserDefinedFunctions.f_FormatString

Произвел вызов функции передав строку форматирования "value1 = {0:0.##}, value2 = {1,3:00}", передал два числа 4.1523 тип money и 7 тип int. Ожидал увидеть результат "value1 = 4.15, value2 = 07", но увидел "value1 = 4,1523, value2 = 7".
Пример вызова:
DECLARE @val1 money, @val2 int
SELECT @val1 = 4.1523, @val2 = 7
SELECT dbo.fe_FormatString('value1 = {0:0.##}, value2 = {1,3:00}', @val1, @val2)

Подскажите, где я допустил ошибку. :(
21 июл 09, 12:19    [7439497]     Ответить | Цитировать Сообщить модератору
 Re: String.Format отказывается форматировать по заданному формату  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74927
автор
Подскажите, где я допустил ошибку. :(


Решили форматировать на стороне сервера СУБД.
21 июл 09, 13:06    [7439854]     Ответить | Цитировать Сообщить модератору
 Re: String.Format отказывается форматировать по заданному формату  [new]
sasharzv
Member

Откуда:
Сообщений: 13
pkarklin,

возникла такая потребность, теперь надо решить
21 июл 09, 13:18    [7439952]     Ответить | Цитировать Сообщить модератору
 Re: String.Format отказывается форматировать по заданному формату  [new]
B0rG
Member

Откуда: столичный город кудаблин
Сообщений: 619
sasharzv,

читать матчасть :)

Mapping CLR Parameter Data

Во вторых, вы параметры передаете как сначала как sql_variant а потом как object. О результирующий типе данных внутри .нет функции можно только догадыватся. По сему String.Format не понимает чего от него хотят и выдает ToString.

Выход только один: писать формат функции отдельно для каждого типа, и передавать тип прямо, а не через sql_variant. Оверлоадов вам тут не будет :-\
21 июл 09, 22:24    [7442574]     Ответить | Цитировать Сообщить модератору
 Re: String.Format отказывается форматировать по заданному формату  [new]
B0rG
Member

Откуда: столичный город кудаблин
Сообщений: 619
Вот мне самому такую шнягу пришлось писать... Может и вам чем то поможет...

CREATE FUNCTION [dbo].fn_CLR_FormatDateValue( 
	@aDateRange nvarchar(20), 
	@aDateLeft datetime) 
returns NVARCHAR(100)
AS EXTERNAL NAME DCSSqlUtils.ReportsHelper.FormatDateValue; 
GO

public static string FormatDateValue( string aDateRange, DateTime aDate)
{

	SuffixType suffix = ProcessSuffix(aDateRange);

	switch ( suffix )
	{

		case SuffixType.Hour:
			return string.Format("{0:HH}:00h", aDate); 
			break; 

		case SuffixType.Day:
			return string.Format("{0:ddd} {0:dd.MM.yy}", aDate);
			break; 

		case SuffixType.Week:
			CultureInfo ciCurr = CultureInfo.CurrentCulture;
			int weekNum = ciCurr.Calendar.GetWeekOfYear(aDate, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
			return string.Format( "Week {0}", weekNum); 
			// return string.Format("{0:ddd} {0:dd.MM.yy}", aDate); 
			break; 

		case SuffixType.Month:
			return string.Format("{0:MMM} {0:yy}", aDate); 
			break; 

		case SuffixType.Year:
			return string.Format("{0:yyyy}", aDate); 
			break; 
	}

	return null;
}

21 июл 09, 22:28    [7442580]     Ответить | Цитировать Сообщить модератору
 Re: String.Format отказывается форматировать по заданному формату  [new]
sasharzv
Member

Откуда:
Сообщений: 13
B0rG

читать матчасть :)

Спасибо. Удивляюсь, как проглядел None на sql_variant :)
22 июл 09, 10:21    [7443597]     Ответить | Цитировать Сообщить модератору
 Re: String.Format отказывается форматировать по заданному формату  [new]
sasharzv
Member

Откуда:
Сообщений: 13
Проблему решил.
На SQL тип sql_variant при использовании в CLR есть управа.
Привожу простенький пример CLR:
[Microsoft.SqlServer.Server.SqlFunction(Name = "fe_FormatString", IsDeterministic = true)]
public static SqlString fe_FormatString(SqlString InStringFormat, System.Object InObj0, System.Object InObj1, System.Object InObj2, System.Object InObj3, System.Object InObj4)
{
    try
    {
        Object[] array = new Object[5];
        array[0] = SqlTypeToObject(InObj0);
        array[1] = SqlTypeToObject(InObj1);
        array[2] = SqlTypeToObject(InObj2);
        array[3] = SqlTypeToObject(InObj3);
        array[4] = SqlTypeToObject(InObj4);
        return new SqlString(String.Format(InStringFormat.ToString(), array));
    }
    catch
    {
    }
    return new SqlString();
}

private static System.Object SqlTypeToObject(System.Object InObj)
{
    try
    {
        if (InObj is SqlString) return ((SqlString)InObj).ToString();
        if (InObj is SqlByte) return (Byte)((SqlByte)InObj).Value;
        if (InObj is SqlInt16) return (Int16)((SqlInt16)InObj).Value;
        if (InObj is SqlInt32) return (Int32)((SqlInt32)InObj).Value;
        if (InObj is SqlInt64) return (Int64)((SqlInt64)InObj).Value;
        if (InObj is SqlSingle) return (Single)((SqlSingle)InObj).Value;
        if (InObj is SqlDouble) return (Double)((SqlDouble)InObj).Value;
        if (InObj is SqlDecimal) return (Decimal)((SqlDecimal)InObj).Value;
        if (InObj is SqlMoney) return (Decimal)((SqlMoney)InObj).Value;
        if (InObj is SqlBoolean) return (Boolean)((SqlBoolean)InObj).Value;
        if (InObj is SqlDateTime) return (DateTime)((SqlDateTime)InObj).Value;
        if (InObj is SqlGuid) return (Guid)((SqlGuid)InObj).Value;
        if (InObj is SqlXml) return ((SqlString)InObj).ToString();
    }
    catch
    {
    }
    return new System.Object();
}
22 июл 09, 18:07    [7447194]     Ответить | Цитировать Сообщить модератору
 Re: String.Format отказывается форматировать по заданному формату  [new]
B0rG
Member

Откуда: столичный город кудаблин
Сообщений: 619
sasharzv
Проблему решил.
На SQL тип sql_variant при использовании в CLR есть управа.
Привожу простенький пример CLR:


Ага, ага. Сам писал таких кодезов много и разных.

В таких ситуациях лучше использовать явное задание типов, потому как неизвестно сколько раз эта функция будет запускаться и для какого количества строк. Особенно в варианте:
SELECT fe_FormatString( "", Field1 ... 
  , fe_FormatString( "", Field2 ... 
  , fe_FormatString( "", Field3 ... 
  , fe_FormatString( "", Field4 ... 

И лучше пускай программер явно вобъет тип (тем паче, что при написании запроса он известен), чем сервер на каждую строку будет проводить несколько операций сравнения и кастинга типов, которые в общем-то не самые дешевые.
23 июл 09, 17:11    [7452764]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить