So nói:Cách T-SQL hiệu quả nhất để đệm một varchar ở bên trái đến một độ dài nhất định?
REPLICATE(@padchar, @len - LEN(@str)) + @str
So nói:Cách T-SQL hiệu quả nhất để đệm một varchar ở bên trái đến một độ dài nhất định?
REPLICATE(@padchar, @len - LEN(@str)) + @str
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.
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. –
+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 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
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)
@padstr = REPLICATE(@padchar, @len) -- this can be cached, done only once
SELECT RIGHT(@padstr + @str, @len)
select right(replicate(@padchar, @len) + @str, @len)
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
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, '_')
Đ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. –
Đ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. –
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.
Làm thế nào về điều này:
replace((space(3 - len(MyField))
3 là số zeros
để pad
Điều này đã giúp tôi: CONCAT (REPLACE (SPACE (@n - LENGTH (@str)), '', '0'), @str) – ingham
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
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. –
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 (...), '') –
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
đâ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)
Bạn dường như đang nói về các số đệm trái như vậy mà '1' trở thành' 001'. –
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)))
Đâ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
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
Để 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.
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. :) –
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
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.
Đâ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 –
Đ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
Đ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 –
Đâ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 và @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;
Tôi đã cuộn lại bản chỉnh sửa cuối cùng. Câu hỏi đưa ra một cách - tôi đang tìm kiếm những cách tối ưu hơn. Bản chỉnh sửa đã mất đi ý nghĩa đó trong việc tìm kiếm một số chất lượng khác. –