String.Format เหมือนการทำงานใน T-SQL?


91

ฉันกำลังมองหาฟังก์ชันในตัว / ฟังก์ชันเพิ่มเติมใน T-SQL สำหรับการจัดการสตริงที่คล้ายกับString.Formatวิธีการใน. NET

คำตอบ:


72

หากคุณใช้ 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');

หมายเหตุ:

  • ไม่มีเอกสารในปี 2555
  • จำกัด ไม่เกิน 2044 อักขระ
  • หากต้องการหลีกเลี่ยงเครื่องหมาย% คุณต้องเพิ่มเป็นสองเท่า
  • หากคุณกำลังบันทึกข้อผิดพลาดในเหตุการณ์เพิ่มเติมการโทรFORMATMESSAGEจะเกิดข้อผิดพลาด (ไม่เป็นอันตราย)

1
หากคุณใช้ SQL 2012 คุณสามารถใช้ฟังก์ชัน FORMAT ได้โดยไม่มีข้อยุ่งยากข้างต้น :)
Reversed Engineer

1
วิธีนี้น่าจะมีคะแนนเสียงมากกว่านี้! การค้นหาที่ยอดเยี่ยมมักจะหลีกเลี่ยงเพราะคิดว่ามันจะใช้งานได้กับในตัวmsg_numberเท่านั้น
Lankymart

1
@Lankymart ชน! ฉันยอมรับว่านี่ควรเป็นคำตอบที่ยอมรับ: เรียบง่ายในตัวและทำงานได้อย่างยอดเยี่ยม
Robert Synoradzki

5
@bijayk ยอมรับเฉพาะชื่อตัวยึดเฉพาะเช่น% s สำหรับสตริง% i สำหรับ ints
g2server

2
@lostmylogin ไม่มีstring.Formatฟังก์ชันการทำงานใน T-SQL ซึ่งเป็นฟังก์ชันที่ใกล้เคียงที่สุดที่คุณจะได้รับ
Ian Kemp

54

จะดูที่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
เพียงแค่ FYI ถ้าพารามิเตอร์ใด ๆ ของคุณมีลูกน้ำแสดงว่าคุณโชคไม่ดี หากคุณบังเอิญผ่านมาคุณจะมีปัญหาในการหาสิ่งที่ผิดพลาด
Kyle

16

ฉันได้สร้างฟังก์ชันที่ผู้ใช้กำหนดขึ้นเพื่อเลียนแบบฟังก์ชัน string.format คุณสามารถใช้งานได้

stringformat-in-sql

อัปเดต:
เวอร์ชันนี้อนุญาตให้ผู้ใช้เปลี่ยนตัวคั่น

-- DROP function will loose the security settings.
IF object_id('[dbo].[svfn_FormatString]') IS NOT NULL
    DROP FUNCTION [dbo].[svfn_FormatString]
GO

CREATE FUNCTION [dbo].[svfn_FormatString]
(
    @Format NVARCHAR(4000),
    @Parameters NVARCHAR(4000),
    @Delimiter CHAR(1) = ','
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    /*
        Name: [dbo].[svfn_FormatString]
        Creation Date: 12/18/2020

        Purpose: Returns the formatted string (Just like in C-Sharp)

        Input Parameters:   @Format         = The string to be Formatted
                            @Parameters     = The comma separated list of parameters
                            @Delimiter      = The delimitter to be used in the formatting process

        Format:             @Format         = N'Hi {0}, Welcome to our site {1}. Thank you {0}'
                            @Parameters     = N'Karthik,google.com'
                            @Delimiter      = ','           
        Examples:
            SELECT dbo.svfn_FormatString(N'Hi {0}, Welcome to our site {1}. Thank you {0}', N'Karthik,google.com', default)
            SELECT dbo.svfn_FormatString(N'Hi {0}, Welcome to our site {1}. Thank you {0}', N'Karthik;google.com', ';')
    */
    DECLARE @Message NVARCHAR(400)
    DECLARE @ParamTable TABLE ( Id INT IDENTITY(0,1), Paramter VARCHAR(1000))

    SELECT @Message = @Format

    ;WITH CTE (StartPos, EndPos) AS
    (
        SELECT 1, CHARINDEX(@Delimiter, @Parameters)
        UNION ALL
        SELECT EndPos + (LEN(@Delimiter)), CHARINDEX(@Delimiter, @Parameters, EndPos + (LEN(@Delimiter)))
        FROM CTE
        WHERE EndPos > 0
    )

    INSERT INTO @ParamTable ( Paramter )
    SELECT
        [Id] = SUBSTRING(@Parameters, StartPos, CASE WHEN EndPos > 0 THEN EndPos - StartPos ELSE 4000 END )
    FROM CTE

    UPDATE @ParamTable 
    SET 
        @Message = REPLACE(@Message, '{'+ CONVERT(VARCHAR, Id) + '}', Paramter )

    RETURN @Message
END

1
ฉันชอบโซลูชันนี้เนื่องจากฉันมีการจองไม่ให้ใช้ฟังก์ชัน xp_ / SP ในการผลิต ฉันใช้รหัสของคุณเป็นฐานและอนุญาตให้มีการส่งผ่านตัวคั่นซึ่งช่วยขจัดความกังวลเกี่ยวกับการใช้เครื่องหมายจุลภาคในข้อมูล
Tim Friesen

4

มีวิธี แต่มันมีข้อ จำกัด คุณสามารถใช้FORMATMESSAGE()ฟังก์ชัน ช่วยให้คุณสามารถจัดรูปแบบสตริงโดยใช้การจัดรูปแบบคล้ายกับprintf()ฟังก์ชันใน C

อย่างไรก็ตามข้อ จำกัด ที่ใหญ่ที่สุดคือจะใช้ได้กับข้อความในตาราง sys.messages เท่านั้น นี่คือบทความเกี่ยวกับเรื่องนี้: microsoft_library_ms186788

เป็นเรื่องที่น่าเสียดายที่ไม่มีวิธีที่ง่ายกว่านี้เนื่องจากมีหลายครั้งที่คุณต้องการจัดรูปแบบสตริง / varchar ในฐานข้อมูล หวังว่าคุณจะต้องการจัดรูปแบบสตริงด้วยวิธีมาตรฐานเท่านั้นและสามารถใช้sys.messagesตารางได้

บังเอิญคุณสามารถใช้RAISERROR()ฟังก์ชั่นที่มีความรุนแรงต่ำมากเอกสารสำหรับการยกระดับความผิดพลาดกล่าวถึงการทำเช่นนี้ แต่ผลลัพธ์จะพิมพ์ออกมาเท่านั้น ดังนั้นคุณจะไม่สามารถทำอะไรกับค่าที่เป็นผลลัพธ์ได้ (จากสิ่งที่ฉันเข้าใจ)

โชคดี!


1
เข้าใจในเรื่องนี้เป็นคำตอบที่เก่า แต่สมมติฐานเกี่ยวกับการFORMATMESSAGE()ไม่ถูกต้อง แต่เข้าใจเพราะมันจะไม่มีเอกสาร แต่มันจะยอมรับสตริงใด ๆ ที่เป็นพารามิเตอร์แรกดูคำตอบนี้โดย@ g2server
Lankymart

@Lankymart คุณถูกต้อง - นี่คือคำตอบเก่า ไม่สามารถเพิ่มความสามารถในการยอมรับสตริงได้จนกระทั่ง SQL 2012
jj

3

Raw t-sql ถูก จำกัด ไว้ที่ CHARINDEX (), PATINDEX (), REPLACE () และ SUBSTRING () สำหรับการจัดการสตริง แต่เมื่อใช้ sql server 2005 ขึ้นไปคุณสามารถตั้งค่าฟังก์ชันที่ผู้ใช้กำหนดเองซึ่งรันใน. Net ซึ่งหมายถึงการตั้งค่า string.format () UDF ไม่ควรยากเกินไป


2

อีกหนึ่งความคิด

แม้ว่านี่จะไม่ใช่วิธีแก้ปัญหาสากล แต่ก็ง่ายและใช้ได้ผลอย่างน้อยสำหรับฉัน :)

สำหรับตัวยึดตำแหน่งเดียว {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

สำหรับตัวยึดตำแหน่งสองตัว {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

สำหรับตัวยึดตำแหน่งสามตัว {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, number, bit และ datetime

ตัวอย่างเช่น:

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


0

จริงๆแล้วไม่มีฟังก์ชันในตัวที่คล้ายกับสตริงฟังก์ชันฟอร์แมตของ. NET มีอยู่ในเซิร์ฟเวอร์ SQL

มีฟังก์ชันFORMATMESSAGE ()ในเซิร์ฟเวอร์ SQL แต่เลียนแบบฟังก์ชัน printf () ของ C ไม่ใช่ฟังก์ชัน string.Format ของ. NET

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.