Szukam funkcji wbudowanej / rozszerzonej w T-SQL do manipulacji ciągami podobnymi do String.Format
metody w .NET.
90
Jeśli używasz programu SQL Server 2012 i nowszych wersji, możesz użyć FORMATMESSAGE
. na przykład.
DECLARE @s NVARCHAR(50) = 'World';
DECLARE @d INT = 123;
SELECT FORMATMESSAGE('Hello %s, %d', @s, @d)
-- RETURNS 'Hello World, 123'
Więcej przykładów z MSDN: FORMATMESSAGE
SELECT FORMATMESSAGE('Signed int %i, %d %i, %d, %+i, %+d, %+i, %+d', 5, -5, 50, -50, -11, -11, 11, 11);
SELECT FORMATMESSAGE('Signed int with leading zero %020i', 5);
SELECT FORMATMESSAGE('Signed int with leading zero 0 %020i', -55);
SELECT FORMATMESSAGE('Unsigned int %u, %u', 50, -50);
SELECT FORMATMESSAGE('Unsigned octal %o, %o', 50, -50);
SELECT FORMATMESSAGE('Unsigned hexadecimal %x, %X, %X, %X, %x', 11, 11, -11, 50, -50);
SELECT FORMATMESSAGE('Unsigned octal with prefix: %#o, %#o', 50, -50);
SELECT FORMATMESSAGE('Unsigned hexadecimal with prefix: %#x, %#X, %#X, %X, %x', 11, 11, -11, 50, -50);
SELECT FORMATMESSAGE('Hello %s!', 'TEST');
SELECT FORMATMESSAGE('Hello %20s!', 'TEST');
SELECT FORMATMESSAGE('Hello %-20s!', 'TEST');
SELECT FORMATMESSAGE('Hello %20s!', 'TEST');
UWAGI:
FORMATMESSAGE
będzie (nieszkodliwe)
msg_number
.string.Format
T-SQL nie ma funkcji stylu, to jest najbliższa, jaką otrzymasz.spójrz na xp_sprintf . przykład poniżej.
DECLARE @ret_string varchar (255) EXEC xp_sprintf @ret_string OUTPUT, 'INSERT INTO %s VALUES (%s, %s)', 'table1', '1', '2' PRINT @ret_string
Wynik wygląda następująco:
INSERT INTO table1 VALUES (1, 2)
Właśnie znalazłem problem z maksymalnym rozmiarem (limit 255 znaków) w ciągu, więc istnieje alternatywna funkcja, której możesz użyć:
create function dbo.fnSprintf (@s varchar(MAX), @params varchar(MAX), @separator char(1) = ',') returns varchar(MAX) as begin declare @p varchar(MAX) declare @paramlen int set @params = @params + @separator set @paramlen = len(@params) while not @params = '' begin set @p = left(@params+@separator, charindex(@separator, @params)-1) set @s = STUFF(@s, charindex('%s', @s), 2, @p) set @params = substring(@params, len(@p)+2, @paramlen) end return @s end
Aby uzyskać taki sam wynik, jak powyżej, wywołaj funkcję w następujący sposób:
print dbo.fnSprintf('INSERT INTO %s VALUES (%s, %s)', 'table1,1,2', default)
źródło
Utworzyłem funkcję zdefiniowaną przez użytkownika, aby naśladować funkcjonalność string.format. Możesz tego użyć.
stringformat-in-sql
źródło
Jest sposób, ale ma on swoje ograniczenia. Możesz użyć
FORMATMESSAGE()
funkcji. Pozwala sformatować ciąg przy użyciu formatowania podobnego doprintf()
funkcji w C.Jednak największym ograniczeniem jest to, że będzie działać tylko z wiadomościami w tabeli sys.messages. Oto artykuł na ten temat: microsoft_library_ms186788
Szkoda, że nie ma prostszego sposobu na zrobienie tego, ponieważ są chwile, kiedy chcesz sformatować ciąg / varchar w bazie danych. Mam nadzieję, że chcesz sformatować ciąg tylko w standardowy sposób i możesz użyć
sys.messages
tabeli.Przypadkowo możesz również użyć
RAISERROR()
funkcji z bardzo niską istotnością, dokumentacja podniesienia błędu nawet wspomina o tym, ale wyniki są tylko drukowane. Więc nie byłbyś w stanie nic zrobić z uzyskaną wartością (z tego, co rozumiem).Powodzenia!
źródło
FORMATMESSAGE()
jest błędne, jednak zrozumiałe, ponieważ jest nieudokumentowane, ale będzie przyjmować dowolny ciąg jako pierwszy parametr, zobacz tę odpowiedź od @ g2server .Surowe t-sql jest ograniczone do CHARINDEX (), PATINDEX (), REPLACE () i SUBSTRING () do manipulacji na ciągach. Ale z sql server 2005 i późniejszymi możesz skonfigurować funkcje zdefiniowane przez użytkownika, które działają w .Net, co oznacza, że ustawienie string.format () UDF nie powinno być zbyt trudne.
źródło
Jeszcze jeden pomysł.
Chociaż nie jest to rozwiązanie uniwersalne - jest proste i działa, przynajmniej dla mnie :)
Dla jednego symbolu zastępczego {0}:
create function dbo.Format1 ( @String nvarchar(4000), @Param0 sql_variant ) returns nvarchar(4000) as begin declare @Null nvarchar(4) = N'NULL'; return replace(@String, N'{0}', cast(isnull(@Param0, @Null) as nvarchar(4000))); end
W przypadku dwóch symboli zastępczych {0} i {1}:
create function dbo.Format2 ( @String nvarchar(4000), @Param0 sql_variant, @Param1 sql_variant ) returns nvarchar(4000) as begin declare @Null nvarchar(4) = N'NULL'; set @String = replace(@String, N'{0}', cast(isnull(@Param0, @Null) as nvarchar(4000))); return replace(@String, N'{1}', cast(isnull(@Param1, @Null) as nvarchar(4000))); end
W przypadku trzech symboli zastępczych {0}, {1} i {2}:
create function dbo.Format3 ( @String nvarchar(4000), @Param0 sql_variant, @Param1 sql_variant, @Param2 sql_variant ) returns nvarchar(4000) as begin declare @Null nvarchar(4) = N'NULL'; set @String = replace(@String, N'{0}', cast(isnull(@Param0, @Null) as nvarchar(4000))); set @String = replace(@String, N'{1}', cast(isnull(@Param1, @Null) as nvarchar(4000))); return replace(@String, N'{2}', cast(isnull(@Param2, @Null) as nvarchar(4000))); end
i tak dalej...
Takie podejście pozwala nam używać tych funkcji w instrukcji SELECT oraz z parametrami typu nvarchar, number, bit i datetime.
Na przykład:
declare @Param0 nvarchar(10) = N'IPSUM' , @Param1 int = 1234567 , @Param2 datetime2(0) = getdate(); select dbo.Format3(N'Lorem {0} dolor, {1} elit at {2}', @Param0, @Param1, @Param2);
źródło
Myślę, że przy obliczaniu pozycji końcowej jest mała korekta.
Oto poprawna funkcja
**>>**IF OBJECT_ID( N'[dbo].[FormatString]', 'FN' ) IS NOT NULL DROP FUNCTION [dbo].[FormatString] GO /*************************************************** Object Name : FormatString Purpose : Returns the formatted string. Original Author : Karthik D V http://stringformat-in-sql.blogspot.com/ Sample Call: SELECT dbo.FormatString ( N'Format {0} {1} {2} {0}', N'1,2,3' ) *******************************************/ CREATE FUNCTION [dbo].[FormatString]( @Format NVARCHAR(4000) , @Parameters NVARCHAR(4000) ) RETURNS NVARCHAR(4000) AS BEGIN --DECLARE @Format NVARCHAR(4000), @Parameters NVARCHAR(4000) select @format='{0}{1}', @Parameters='hello,world' DECLARE @Message NVARCHAR(400), @Delimiter CHAR(1) DECLARE @ParamTable TABLE ( ID INT IDENTITY(0,1), Parameter VARCHAR(1000) ) Declare @startPos int, @endPos int SELECT @Message = @Format, @Delimiter = ','**>>** --handle first parameter set @endPos=CHARINDEX(@Delimiter,@Parameters) if (@endPos=0 and @Parameters is not null) --there is only one parameter insert into @ParamTable (Parameter) values(@Parameters) else begin insert into @ParamTable (Parameter) select substring(@Parameters,0,@endPos) end while @endPos>0 Begin --insert a row for each parameter in the set @startPos = @endPos + LEN(@Delimiter) set @endPos = CHARINDEX(@Delimiter,@Parameters, @startPos) if (@endPos>0) insert into @ParamTable (Parameter) select substring(@Parameters,@startPos,@endPos - @startPos) else insert into @ParamTable (Parameter) select substring(@Parameters,@startPos,4000) End UPDATE @ParamTable SET @Message = REPLACE ( @Message, '{'+CONVERT(VARCHAR,ID) + '}', Parameter ) RETURN @Message END Go grant execute,references on dbo.formatString to public
źródło
Oto moja wersja. Można rozszerzyć, aby pomieścić większą liczbę parametrów i rozszerzyć formatowanie w oparciu o typ. Obecnie formatowane są tylko typy daty i godziny.
Przykład:
select dbo.FormatString('some string %s some int %s date %s','"abcd"',100,cast(getdate() as date),DEFAULT,DEFAULT) select dbo.FormatString('some string %s some int %s date time %s','"abcd"',100,getdate(),DEFAULT,DEFAULT)
Wynik:
Funkcje:
create function dbo.FormatValue(@param sql_variant) returns nvarchar(100) begin /* Tejasvi Hegde, 29-April-2017 Can extend formatting here. */ declare @result nvarchar(100) if (SQL_VARIANT_PROPERTY(@param,'BaseType') in ('date')) begin select @result = REPLACE(CONVERT(CHAR(11), @param, 106), ' ', '-') end else if (SQL_VARIANT_PROPERTY(@param,'BaseType') in ('datetime','datetime2')) begin select @result = REPLACE(CONVERT(CHAR(11), @param, 106), ' ', '-')+' '+CONVERT(VARCHAR(5),@param,108) end else begin select @result = cast(@param as nvarchar(100)) end return @result /* BaseType: bigint binary char date datetime datetime2 datetimeoffset decimal float int money nchar numeric nvarchar real smalldatetime smallint smallmoney time tinyint uniqueidentifier varbinary varchar */ end; create function dbo.FormatString( @format nvarchar(4000) ,@param1 sql_variant = null ,@param2 sql_variant = null ,@param3 sql_variant = null ,@param4 sql_variant = null ,@param5 sql_variant = null ) returns nvarchar(4000) begin /* Tejasvi Hegde, 29-April-2017 select dbo.FormatString('some string value %s some int %s date %s','"abcd"',100,cast(getdate() as date),DEFAULT,DEFAULT) select dbo.FormatString('some string value %s some int %s date time %s','"abcd"',100,getdate(),DEFAULT,DEFAULT) */ declare @result nvarchar(4000) select @param1 = dbo.formatValue(@param1) ,@param2 = dbo.formatValue(@param2) ,@param3 = dbo.formatValue(@param3) ,@param4 = dbo.formatValue(@param4) ,@param5 = dbo.formatValue(@param5) select @param2 = cast(@param2 as nvarchar) EXEC xp_sprintf @result OUTPUT,@format , @param1, @param2, @param3, @param4, @param5 return @result end;
źródło
oto, co znalazłem podczas moich eksperymentów z użyciem wbudowanego
FORMATMESSAGE ()
sp_addmessage @msgnum=50001,@severity=1,@msgText='Hello %s you are #%d',@replace='replace' SELECT FORMATMESSAGE(50001, 'Table1', 5)
kiedy wywołujesz sp_addmessage, szablon wiadomości zostaje zapisany w tabeli systemowej master.dbo.sysmessages (zweryfikowany na SQLServer 2000).
Musisz samodzielnie zarządzać dodawaniem i usuwaniem ciągów szablonów z tabeli, co jest niewygodne, jeśli naprawdę chcesz tylko wyświetlić szybką wiadomość na ekranie wyników.
Rozwiązanie dostarczone przez Kathik DV wygląda interesująco, ale nie działa z SQL Server 2000, więc trochę je zmieniłem i ta wersja powinna działać ze wszystkimi wersjami SQL Server:
IF OBJECT_ID( N'[dbo].[FormatString]', 'FN' ) IS NOT NULL DROP FUNCTION [dbo].[FormatString] GO /*************************************************** Object Name : FormatString Purpose : Returns the formatted string. Original Author : Karthik D V http://stringformat-in-sql.blogspot.com/ Sample Call: SELECT dbo.FormatString ( N'Format {0} {1} {2} {0}', N'1,2,3' ) *******************************************/ CREATE FUNCTION [dbo].[FormatString]( @Format NVARCHAR(4000) , @Parameters NVARCHAR(4000) ) RETURNS NVARCHAR(4000) AS BEGIN --DECLARE @Format NVARCHAR(4000), @Parameters NVARCHAR(4000) select @format='{0}{1}', @Parameters='hello,world' DECLARE @Message NVARCHAR(400), @Delimiter CHAR(1) DECLARE @ParamTable TABLE ( ID INT IDENTITY(0,1), Parameter VARCHAR(1000) ) Declare @startPos int, @endPos int SELECT @Message = @Format, @Delimiter = ',' --handle first parameter set @endPos=CHARINDEX(@Delimiter,@Parameters) if (@endPos=0 and @Parameters is not null) --there is only one parameter insert into @ParamTable (Parameter) values(@Parameters) else begin insert into @ParamTable (Parameter) select substring(@Parameters,0,@endPos) end while @endPos>0 Begin --insert a row for each parameter in the set @startPos = @endPos + LEN(@Delimiter) set @endPos = CHARINDEX(@Delimiter,@Parameters, @startPos) if (@endPos>0) insert into @ParamTable (Parameter) select substring(@Parameters,@startPos,@endPos) else insert into @ParamTable (Parameter) select substring(@Parameters,@startPos,4000) End UPDATE @ParamTable SET @Message = REPLACE ( @Message, '{'+CONVERT(VARCHAR,ID) + '}', Parameter ) RETURN @Message END Go grant execute,references on dbo.formatString to public
Stosowanie:
print dbo.formatString('hello {0}... you are {1}','world,good') --result: hello world... you are good
źródło
W tej chwili tak naprawdę nie istnieje (chociaż możesz oczywiście napisać własne). Występuje dla niego błąd otwartego połączenia: https://connect.microsoft.com/SQLServer/Feedback/Details/3130221 , który w chwili pisania tego tekstu ma tylko 1 głos.
źródło
Właściwie nie ma wbudowanej funkcji podobnej do stringa. Funkcja formatowania .NET jest dostępna w serwerze SQL.
Istnieje funkcja FORMATMESSAGE () na serwerze SQL, ale naśladuje ona funkcję printf () w języku C, a nie funkcję string.Format w .NET.
SELECT FORMATMESSAGE('This is the %s and this is the %s.', 'first variable', 'second variable') AS Result
źródło
Niezupełnie, ale chciałbym sprawdzić niektóre artykuły na temat obsługi ciągów (między innymi) przez „Phil Factor” (geddit?) Na Simple Talk.
źródło
to jest złe podejście. powinieneś pracować z bibliotekami DLL assemblera, w których zrobisz to samo z lepszą wydajnością.
źródło