String.Format như chức năng trong T-SQL?


89

Tôi đang tìm một hàm tích hợp / hàm mở rộng trong T-SQL để thao tác chuỗi tương tự như String.Formatphương thức trong .NET.

Câu trả lời:


70

Nếu bạn đang sử dụng SQL Server 2012 trở lên, bạn có thể sử dụng FORMATMESSAGE. ví dụ.

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

Các ví dụ khác từ 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');

LƯU Ý:

  • Không có giấy tờ vào năm 2012
  • Giới hạn trong 2044 ký tự
  • Để thoát khỏi dấu%, bạn cần phải nhân đôi nó.
  • Nếu bạn gặp lỗi ghi nhật ký trong các sự kiện mở rộng, việc gọi sẽ FORMATMESSAGExuất hiện dưới dạng lỗi (vô hại)

1
Nếu bạn đang sử dụng SQL 2012, bạn có thể sử dụng chức năng FORMAT mà không cần tất cả các biến chứng ở trên :)
Kỹ sư đảo ngược

1
Điều này sẽ có nhiều phiếu bầu hơn! Luôn tránh tìm kiếm tuyệt vời vì giả định rằng nó sẽ chỉ hoạt động với tích hợp sẵn msg_number.
Lankymart

1
@Lankymart, xóc! Tôi đồng ý rằng đây phải là câu trả lời được chấp nhận: đơn giản, tích hợp sẵn và hoạt động hiệu quả.
Robert Synoradzki

5
@bijayk nó chỉ chấp nhận các tên trình giữ chỗ cụ thể, ví dụ:% s cho chuỗi,% i cho int.
g2server,

2
@lostmylogin Không có string.Formatchức năng kiểu trong T-SQL, đây là chức năng gần nhất bạn sẽ nhận được.
Ian Kemp

53

hãy xem xp_sprintf . ví dụ bên dưới.

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

Kết quả như sau:

INSERT INTO table1 VALUES (1, 2)

Vừa tìm thấy một vấn đề với kích thước tối đa (giới hạn 255 ký tự) của chuỗi này, vì vậy có một hàm thay thế bạn có thể sử dụng:

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

Để nhận được kết quả tương tự như trên, bạn gọi hàm như sau:

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

7
Chỉ là FYI nếu bất kỳ thông số nào của bạn chứa dấu phẩy thì bạn không gặp may. Nếu bạn tình cờ vượt qua một chiếc xe, bạn sẽ gặp một số khó khăn trong việc tìm ra điều gì đã xảy ra.
Kyle

15

Tôi đã tạo một hàm do người dùng xác định để bắt chước chức năng string.format. Bạn co thể sử dụng no.

stringformat-in-sql


Tôi thích giải pháp này vì tôi đã bảo lưu việc sử dụng xp_ functions / SPs trong sản xuất. Tôi đã sử dụng mã của bạn làm cơ sở và cho phép chuyển dấu phân cách, điều này giúp loại bỏ mọi lo lắng về dấu phẩy được sử dụng trong dữ liệu.
Tim Friesen

4

Có một cách, nhưng nó có những hạn chế của nó. Bạn có thể sử dụng FORMATMESSAGE()chức năng. Nó cho phép bạn định dạng một chuỗi bằng cách sử dụng định dạng tương tự như printf()hàm trong C.

Tuy nhiên, hạn chế lớn nhất là nó sẽ chỉ hoạt động với các thư trong bảng sys.messages. Đây là một bài viết về nó: microsoft_library_ms186788

Thật tiếc là không có cách nào dễ dàng hơn để làm điều này, bởi vì đôi khi bạn muốn định dạng một chuỗi / varchar trong cơ sở dữ liệu. Hy vọng rằng bạn chỉ đang tìm cách định dạng một chuỗi theo cách chuẩn và có thể sử dụng sys.messagesbảng.

Thật trùng hợp, bạn cũng có thể sử dụng RAISERROR()hàm với mức độ nghiêm trọng rất thấp, tài liệu về lỗi nâng cao thậm chí còn đề cập đến việc làm này, nhưng kết quả chỉ được in ra. Vì vậy, bạn sẽ không thể làm bất cứ điều gì với giá trị kết quả (theo những gì tôi hiểu).

Chúc may mắn!


1
Hiểu đây là một câu trả lời cũ nhưng giả định về FORMATMESSAGE()là không chính xác, tuy nhiên có thể hiểu được vì nó không có tài liệu nhưng nó sẽ chấp nhận bất kỳ chuỗi nào làm tham số đầu tiên, hãy xem câu trả lời này của @ g2server .
Lankymart

@Lankymart Bạn đúng - đây là một câu trả lời cũ. Khả năng chấp nhận một chuỗi không được thêm vào cho đến SQL 2012.
jj.

3

Raw t-sql được giới hạn ở CHARINDEX (), PATINDEX (), REPLACE () và SUBSTRING () cho thao tác chuỗi. Nhưng với sql server 2005 trở lên, bạn có thể thiết lập các hàm do người dùng xác định chạy trong .Net, có nghĩa là việc thiết lập một UDF string.format () sẽ không quá khó.


2

Thêm một ý tưởng nữa.

Mặc dù đây không phải là một giải pháp phổ biến - nó đơn giản và hiệu quả, ít nhất là đối với tôi :)

Đối với một trình giữ chỗ {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

Đối với hai trình giữ chỗ {0} và {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

Đối với ba trình giữ chỗ {0}, {1} và {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

và như thế...

Cách tiếp cận như vậy cho phép chúng ta sử dụng các hàm này trong câu lệnh SELECT và với các tham số kiểu dữ liệu nvarchar, number, bit và datetime.

Ví dụ:

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

Tôi nghĩ rằng có một sự điều chỉnh nhỏ trong khi tính toán vị trí kết thúc.

Đây là chức năng chính xác

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

Đây là phiên bản của tôi. Có thể mở rộng để chứa nhiều thông số hơn và có thể mở rộng định dạng dựa trên loại. Hiện tại chỉ có loại ngày tháng và ngày giờ được định dạng.

Thí dụ:

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)

Đầu ra:

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

Chức năng:

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;

Câu trả lời đơn giản nhất cho SQL Server 2008+. Giữ đầu vào dưới dạng các tham số riêng biệt. Sử dụng hàm xp_sprintf và có thể mở rộng dễ dàng. xp_sprintf - docs.microsoft.com/en-us/sql/relational-databases/…
Jeff Lewis

0

đây là những gì tôi tìm thấy với các thử nghiệm của mình bằng cách sử dụng

Hàm FORMATMESSAGE ()

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

khi bạn gọi sp_addmessage, mẫu thông báo của bạn sẽ được lưu trữ trong bảng hệ thống master.dbo.sysmessages (được xác minh trên SQLServer 2000).

Bạn phải tự quản lý việc thêm và xóa các chuỗi mẫu khỏi bảng, điều này thật khó xử nếu tất cả những gì bạn thực sự muốn là xuất một thông báo nhanh ra màn hình kết quả.

Giải pháp do Kathik DV cung cấp, có vẻ thú vị nhưng không hoạt động với SQL Server 2000, vì vậy tôi đã thay đổi nó một chút và phiên bản này sẽ hoạt động với tất cả các phiên bản của 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

Sử dụng:

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


-1

Trên thực tế, không có chức năng tích hợp nào tương tự như string. Chức năng định dạng của .NET có sẵn trong máy chủ SQL.

Có một hàm FORMATMESSAGE () trong máy chủ SQL nhưng nó bắt chước hàm printf () của C chứ không phải hàm string.Format của .NET.

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

-2

Không chính xác, nhưng tôi sẽ xem một số bài viết về xử lý chuỗi (trong số những thứ khác) của "Phil Factor" (geddit?) Trên Simple Talk.


-3

đây là cách tiếp cận tồi. bạn nên làm việc với assembly dll, trong đó sẽ làm điều tương tự cho bạn với hiệu suất tốt hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.