2008-09-23 25 views

Trả lời

302

này chỉ đơn giản là việc sử dụng kém hiệu quả của SQL, không có vấn đề làm thế nào bạn làm điều đó.

có lẽ cái gì đó như

right('XXXXXXXXXXXX'+ rtrim(@str), @n) 

trong đó X là nhân vật đệm của bạn và @n là số ký tự trong chuỗi kết quả (giả sử bạn cần padding vì bạn đang đối phó với một chiều dài cố định).

Nhưng như tôi đã nói bạn nên thực sự tránh làm điều này trong cơ sở dữ liệu của bạn.

+1

Có những lúc cần thiết ... ví dụ, tìm nạp một tập hợp con dữ liệu cho màn hình được phân trang. –

+6

+1 Chỉ cần thử nghiệm một tải các phương pháp khác nhau và đây là nhanh nhất. Bạn có thể cần 'RTRIM (@str)' mặc dù nếu nó có thể chứa dấu cách. –

+1

+1 Thật khó hiểu vì sao char của tôi (6) không được đệm đúng cách, và RTRIM trên biến đầu vào đã giúp tôi tránh bị trầy xước – jkelley

6

Tôi không chắc chắn rằng phương pháp mà bạn đưa ra thực sự không hiệu quả, nhưng một cách khác, miễn là nó không phải linh hoạt trong độ dài hoặc ký tự đệm, sẽ là (giả sử rằng bạn muốn pad nó bằng "0" đến 10 ký tự.

DECLARE 
    @pad_characters VARCHAR(10) 

SET @pad_characters = '0000000000' 

SELECT RIGHT(@pad_characters + @str, 10) 
15
@padstr = REPLICATE(@padchar, @len) -- this can be cached, done only once 

SELECT RIGHT(@padstr + @str, @len) 
1
select right(replicate(@padchar, @len) + @str, @len) 
2

Trong SQL server 2005 và sau đó bạn có thể tạo ra một chức năng CLR để làm điều này

2

lẽ overkill, tôi thường sử dụng này UDF:

CREATE FUNCTION [dbo].[f_pad_before](@string VARCHAR(255), @desired_length INTEGER, @pad_character CHAR(1)) 
RETURNS VARCHAR(255) AS 
BEGIN 

-- Prefix the required number of spaces to bulk up the string and then replace the spaces with the desired character 
RETURN ltrim(rtrim(
     CASE 
      WHEN LEN(@string) < @desired_length 
      THEN REPLACE(SPACE(@desired_length - LEN(@string)), ' ', @pad_character) + @string 
      ELSE @string 
     END 
     )) 
END 

Vì vậy mà bạn có thể làm những việc như:

select dbo.f_pad_before('aaa', 10, '_') 
+0

Điều này thực sự được sử dụng trong một udf mà phải làm một vài thứ khác để phù hợp với một số dữ liệu. –

+0

Điều này cũng hoạt động hoàn hảo nếu bạn đang kết hợp các loại char và varchar. –

35

Một số người cho phiên bản này:

right('XXXXXXXXXXXX'+ @str, @n) 

hãy cẩn thận với điều đó bởi vì nó sẽ cắt xén dữ liệu thực tế của bạn nếu nó là dài hơn n.

1

Làm thế nào về điều này:

replace((space(3 - len(MyField)) 

3 là số zeros để pad

+0

Điều này đã giúp tôi: CONCAT (REPLACE (SPACE (@n - LENGTH (@str)), '', '0'), @str) – ingham

9

Có lẽ một kill qua tôi có những UDFs để pad trái và phải

ALTER Function [dbo].[fsPadLeft](@var varchar(200),@padChar char(1)='0',@len int) 
returns varchar(300) 
as 
Begin 

return replicate(@PadChar,@len-Len(@var))[email protected] 

end 

và sang phải

ALTER function [dbo].[fsPadRight](@var varchar(200),@padchar char(1)='0', @len int) returns varchar(201) as 
Begin 

--select @padChar=' ',@len=200,@var='hello' 


return @var+replicate(@PadChar,@len-Len(@var)) 
end 
+0

Vấn đề duy nhất với UDF vô hướng là chúng hoạt động kém hơn nhiều so với mã nội tuyến tương đương (cộng với các vấn đề về kiểu dữ liệu). Dưới đây là hy vọng họ giới thiệu hiệu suất UDF vô hướng tốt hơn và/hoặc UDF vô hướng trong một phiên bản trong tương lai. –

+0

Nếu bạn chỉ định độ dài nhỏ hơn chiều dài của var, thì các hàm này trả về giá trị rỗng. Bao bọc từng câu lệnh lặp lại với câu lệnh isnull để trả về var nếu chiều dài nhỏ hơn. isnull (replicate (...), '') –

+0

Thêm WITH SCHEMABINDING vào khai báo hàm sẽ cải thiện hiệu quả của các hàm do người dùng định nghĩa. Đây là điều tôi khuyên bạn nên thêm theo mặc định cho tất cả các chức năng của bạn trừ khi bạn có lý do thuyết phục để xóa nó. – EricI

2

đây là một cách đơn giản để pad trái:

REPLACE(STR(FACT_HEAD.FACT_NO, x, 0), ' ', y) 

đâu x là số pad và y là nhân vật pad.

mẫu:

REPLACE(STR(FACT_HEAD.FACT_NO, 3, 0), ' ', 0) 
+0

Bạn dường như đang nói về các số đệm trái như vậy mà '1' trở thành' 001'. –

1

Tôi hy vọng điều này sẽ giúp một ai đó.

STUFF (character_expression, bắt đầu, chiều dài, character_expression)

chọn thứ (@str, 1, 0, tái tạo ('0', @n - len (@str)))

-4

Đây là làm thế nào tôi sẽ thường pad một varchar

WHILE Len(@String) < 8 
BEGIN 
    SELECT @String = '0' + @String 
END 
+13

Wow, điều này thật đáng kinh ngạc. – Hogan

+1

Các vòng lặp, con trỏ, v.v ... tất cả đều xấu trong SQL. Có thể tốt trong mã ứng dụng nhưng không phải trong SQL. Một số trường hợp ngoại lệ nhưng đây không phải là một trong số đó. – Davos

2

tôi thích vnRocks giải pháp, ở đây nó là trong hình thức của một udf

create function PadLeft(
     @String varchar(8000) 
    ,@NumChars int 
    ,@PadChar char(1) = ' ') 
returns varchar(8000) 
as 
begin 
    return stuff(@String, 1, 0, replicate(@PadChar, @NumChars - len(@String))) 
end 
0

Để cung cấp các giá trị số được làm tròn đến hai chữ số thập phân nhưng phải đệm bằng số không nếu cần tôi có:

DECLARE @value = 20.1 
SET @value = ROUND(@value,2) * 100 
PRINT LEFT(CAST(@value AS VARCHAR(20)), LEN(@value)-2) + '.' + RIGHT(CAST(@value AS VARCHAR(20)),2) 

Nếu bất cứ ai có thể nghĩ ra một cách gọn gàng, điều đó sẽ được đánh giá cao - dường như vụng trên.

Lưu ý: trong trường hợp này, tôi đang sử dụng SQL Server để gửi báo cáo qua email ở định dạng HTML và mong muốn định dạng thông tin mà không cần thêm công cụ phân tích cú pháp dữ liệu.

+0

Không biết SQL Server cho phép bạn khai báo một biến mà không chỉ rõ kiểu của nó. Dù sao, phương pháp của bạn dường như "vụng về" đối với một người không làm việc. :) –

0

Tôi sử dụng cái này. Nó cho phép bạn xác định độ dài bạn muốn kết quả cũng như một ký tự đệm mặc định nếu một ký tự không được cung cấp. Tất nhiên bạn có thể tùy chỉnh độ dài của đầu vào và đầu ra cho bất kỳ mức tối đa nào bạn đang chạy vào.

/*=============================================================== 
Author   : Joey Morgan 
Create date : November 1, 2012 
Description : Pads the string @MyStr with the character in 
       : @PadChar so all results have the same length 
================================================================*/ 
CREATE FUNCTION [dbo].[svfn_AMS_PAD_STRING] 
     (
     @MyStr VARCHAR(25), 
     @LENGTH INT, 
     @PadChar CHAR(1) = NULL 
     ) 
RETURNS VARCHAR(25) 
AS 
     BEGIN 
     SET @PadChar = ISNULL(@PadChar, '0'); 
     DECLARE @Result VARCHAR(25); 
     SELECT 
      @Result = RIGHT(SUBSTRING(REPLICATE('0', @LENGTH), 1, 
             (@LENGTH + 1) - LEN(RTRIM(@MyStr))) 
          + RTRIM(@MyStr), @LENGTH) 

     RETURN @Result 

     END 

Số dặm của bạn có thể thay đổi. :-)

Joey Morgan
Programmer/nhà phân tích chính tôi Unit
WellPoint Medicaid Business

43

Tôi biết điều này ban đầu được hỏi lại trong năm 2008, nhưng có một số chức năng mới được giới thiệu với SQL Server 2012. Các FORMAT function đơn giản hóa padding trái với số không độc đáo. Nó cũng sẽ thực hiện việc chuyển đổi cho bạn:

declare @n as int = 2 
select FORMAT(@n, 'd10') as padWithZeros 

Cập nhật:

tôi muốn kiểm tra hiệu quả thực tế của hàm FORMAT bản thân mình. Tôi khá ngạc nhiên khi thấy hiệu quả không tốt lắm so với câu trả lời ban đầu từ AlexCuse. Mặc dù tôi tìm thấy trình dọn dẹp chức năng FORMAT, nhưng nó không phải là rất hiệu quả về thời gian thực hiện. Bảng Tally tôi đã sử dụng có 64.000 bản ghi. Kudos để Martin Smith để chỉ ra hiệu quả thời gian thực hiện.

SET STATISTICS TIME ON 
select FORMAT(N, 'd10') as padWithZeros from Tally 
SET STATISTICS TIME OFF 

Thời gian thực thi SQL Server: Thời gian CPU = 2157 ms, thời gian trôi qua = 2696 ms.

SET STATISTICS TIME ON 
select right('0000000000'+ rtrim(cast(N as varchar(5))), 10) from Tally 
SET STATISTICS TIME OFF 

SQL Server Thực hiện Times: thời gian

CPU = 31 ms, thời gian trôi qua = 235 ms.

+1

Đây chính xác là những gì tôi đang tìm kiếm. Trợ giúp chính thức cho FORMAT: https://msdn.microsoft.com/es-MX/library/hh213505.aspx –

+1

Điều này áp dụng cho SQL Server 2014 trở đi theo MSDN và trải nghiệm của riêng tôi về việc thử nó trên SQL Server 2012. – arame3333

+4

Điều này sẽ không phải là cách "hiệu quả nhất" theo yêu cầu. Trong ví dụ này Định dạng mất 180 giây so với 12 giây. http://stackoverflow.com/a/27447244/73226 –

0

Đây là giải pháp của tôi, tránh các chuỗi bị cắt bớt và sử dụng SQL đơn giản.Cảm ơn @AlexCuse, @Kevin@Sklivvz, các giải pháp là nền tảng của mã này.

--[@charToPadStringWith] is the character you want to pad the string with. 
declare @charToPadStringWith char(1) = 'X'; 

-- Generate a table of values to test with. 
declare @stringValues table (RowId int IDENTITY(1,1) NOT NULL PRIMARY KEY, StringValue varchar(max) NULL); 
insert into @stringValues (StringValue) values (null), (''), ('_'), ('A'), ('ABCDE'), ('1234567890'); 

-- Generate a table to store testing results in. 
declare @testingResults table (RowId int IDENTITY(1,1) NOT NULL PRIMARY KEY, StringValue varchar(max) NULL, PaddedStringValue varchar(max) NULL); 

-- Get the length of the longest string, then pad all strings based on that length. 
declare @maxLengthOfPaddedString int = (select MAX(LEN(StringValue)) from @stringValues); 
declare @longestStringValue varchar(max) = (select top(1) StringValue from @stringValues where LEN(StringValue) = @maxLengthOfPaddedString); 
select [@longestStringValue][email protected], [@maxLengthOfPaddedString][email protected]; 

-- Loop through each of the test string values, apply padding to it, and store the results in [@testingResults]. 
while (1=1) 
begin 
    declare 
     @stringValueRowId int, 
     @stringValue varchar(max); 

    -- Get the next row in the [@stringLengths] table. 
    select top(1) @stringValueRowId = RowId, @stringValue = StringValue 
    from @stringValues 
    where RowId > isnull(@stringValueRowId, 0) 
    order by RowId; 

    if (@@ROWCOUNT = 0) 
     break; 

    -- Here is where the padding magic happens. 
    declare @paddedStringValue varchar(max) = RIGHT(REPLICATE(@charToPadStringWith, @maxLengthOfPaddedString) + @stringValue, @maxLengthOfPaddedString); 

    -- Added to the list of results. 
    insert into @testingResults (StringValue, PaddedStringValue) values (@stringValue, @paddedStringValue); 
end 

-- Get all of the testing results. 
select * from @testingResults; 
Các vấn đề liên quan