T-SQLの機能のようなString.Format?


89

String.Format.NET のメソッドに似た文字列操作用のT-SQLの組み込み関数/拡張関数を探しています。

回答:


70

SQL Server 2012以降を使用してFORMATMESSAGEいる場合は、を使用できます。例えば。

DECLARE @s NVARCHAR(50) = 'World';
DECLARE @d INT = 123;
SELECT FORMATMESSAGE('Hello %s, %d', @s, @d)
-- RETURNS 'Hello World, 123'

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');

ノート:

  • 2012年には文書化されていません
  • 2044文字に制限されています
  • %記号をエスケープするには、2倍にする必要があります。
  • 拡張イベントでエラーを記録している場合、呼び出しFORMATMESSAGEは(無害な)エラーとして表示されます

1
SQL 2012を使用している場合は、上記の複雑な作業をすべて行わずにFORMAT関数を使用できます:)
リバースエンジニア

1
これにはもっと多くの票があるはずです!ビルトインでのみ機能すると想定されていたため、素晴らしい検索は常に回避されましたmsg_number
Lankymart 2016年

1
@Lankymart、バンプ!これは受け入れられる答えであることに同意します。シンプルで、組み込みであり、見事に機能しました。
Robert Synoradzki

5
@bijaykこれは、特定のプレースホルダー名のみを受け入れます。たとえば、文字列の場合は%s、intの場合は%iです。
g2server 2016

2
@lostmylogin string.FormatT-SQLにはスタイル形式の機能はありません。これが最も近い機能です。
イアンケンプ

53

xp_sprintfを見てください。以下の例。

DECLARE @ret_string varchar (255)
EXEC xp_sprintf @ret_string OUTPUT, 
    'INSERT INTO %s VALUES (%s, %s)', 'table1', '1', '2'
PRINT @ret_string

結果は次のようになります。

INSERT INTO table1 VALUES (1, 2)

これで文字列の最大サイズ(255文字の制限)の問題を見つけたので、使用できる代替関数があります。

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

上記と同じ結果を得るには、次のように関数を呼び出します。

print dbo.fnSprintf('INSERT INTO %s VALUES (%s, %s)', 'table1,1,2', default)

7
参考までに、パラメータにカンマが含まれている場合は、運が悪かったことになります。偶然に合格した場合、何が問題かを理解するのにいくつかの問題が発生します。
カイル

15

string.format機能を模倣するユーザー定義関数を作成しました。使用できます。

stringformat-in-sql


本番環境でxp_ functions / SPsを使用することに対して予約があるため、このソリューションが好きです。私はあなたのコードをベースとして使用し、区切り文字を渡すことを許可しました。これにより、データで使用されるコンマについての心配がなくなります。
Tim Friesen、2012年

4

方法はありますが、制限があります。FORMATMESSAGE()関数を使用できます。printf()C の関数と同様のフォーマットを使用して文字列をフォーマットできます。

ただし、最大の制限は、sys.messagesテーブル内のメッセージでのみ機能することです。これに関する記事は次のとおりです。。microsoft_library_ms186788

データベースで文字列/ varcharをフォーマットする必要がある場合があるため、これを行う簡単な方法はありません。うまくいけば、あなたは標準的な方法で文字列をフォーマットすることだけを考えており、sys.messagesテーブルを使用することができます。

偶然にもRAISERROR()、非常に低い重大度で関数を使用することもできます。raiseerrorのドキュメントでは、これを行うことについても言及していますが、結果は出力されるだけです。したがって、(私が理解していることから)結果の値を使用して何かを行うことはできません。

幸運を!


1
これは古い答えですが、仮定FORMATMESSAGE()は正しくありませんが、文書化されていないため理解できますが、最初のパラメータとして任意の文字列を受け入れます。@ g2serverによるこの答えを参照してください。
Lankymart 2016年

@Lankymart正解です-これは古い答えです。文字列を受け入れる能力は、SQL、2012年までは添加しなかった
JJ。

3

未加工のt-sqlは、文字列操作のCHARINDEX()、PATINDEX()、REPLACE()、およびSUBSTRING()に制限されています。しかし、SQL Server 2005以降では、.Netで実行されるユーザー定義関数を設定できます。つまり、string.format()UDFの設定はそれほど難しくありません。


2

もう一つのアイデア。

これは普遍的な解決策ではありませんが、少なくとも私にとってはシンプルで機能します:)

1つのプレースホルダー{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

2つのプレースホルダー{0}および{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

3つのプレースホルダー{0}、{1}、{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

等々...

そのようなアプローチにより、これらの関数をSELECTステートメントで使用でき、nvarchar、数値、ビット、および日時データ型のパラメーターを使用できます。

例えば:

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);  

1

終了位置を計算するときに小さな修正があると思います。

これは正しい機能です

**>>**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 

1

これが私のバージョンです。より多くのパラメーターに対応するように拡張でき、タイプに基づいてフォーマットを拡張できます。現在、日付と日時タイプのみがフォーマットされます。

例:

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)

出力:

some string "abcd" some int 100 date 29-Apr-2017
some string "abcd" some int 100 date time 29-Apr-2017 19:40

関数:

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;

SQL Server 2008以降の最も簡単な答え。入力を個別のパラメーターとして保持します。xp_sprintf関数を使用し、簡単に拡張できます。xp_sprintf-docs.microsoft.com/en-us/sql/relational-databases/…–
Jeff Lewis

0

これは、組み込みを使用した実験で見つけたものです

FORMATMESSAGE()関数

sp_addmessage @msgnum=50001,@severity=1,@msgText='Hello %s you are #%d',@replace='replace'
SELECT FORMATMESSAGE(50001, 'Table1', 5)

sp_addmessageを呼び出すと、メッセージテンプレートがシステムテーブルmaster.dbo.sysmessages(SQLServer 2000で検証済み)に格納されます。

テーブルからのテンプレート文字列の追加と削除は自分で管理する必要があります。これは、結果画面に簡単なメッセージを出力するだけの場合は厄介です。

Kathik DVによって提供されたソリューションは興味深いように見えますが、SQL Server 2000では機能しないため、少し変更しました。このバージョンは、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

使用法:

print dbo.formatString('hello {0}... you are {1}','world,good')
--result: hello world... you are good


-1

実際には、SQLサーバーでは.NETのstring.Format関数に似た組み込み関数はありません。

SQLサーバーにはFORMATMESSAGE()関数がありますが、.NETのstring.Format関数ではなく、Cのprintf()関数に似ています。

SELECT FORMATMESSAGE('This is the %s and this is the %s.', 'first variable', 'second variable') AS Result


-3

これは悪いアプローチです。アセンブリDLLを使用する必要があります。これにより、パフォーマンスが向上します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.