Câu trả lời:
Đây đơn giản là việc sử dụng SQL không hiệu quả, bất kể bạn làm như thế nào.
có lẽ một cái gì đó như
right('XXXXXXXXXXXX'+ rtrim(@str), @n)
Trong đó X là ký tự đệm của bạn và @n là số ký tự trong chuỗi kết quả (giả sử bạn cần đệm vì bạn đang xử lý một độ dài cố định).
Nhưng như tôi đã nói, bạn thực sự nên tránh làm điều này trong cơ sở dữ liệu của bạn.
RTRIM(@str)
mặc dù nếu điều đó có thể chứa dấu cách.
Tôi biết điều này ban đầu được hỏi lại vào 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. Hàm FORMAT đơn giản hóa phần đệm còn lại với số không độc đáo. Nó cũng sẽ thực hiện 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 tự mình kiểm tra hiệu quả thực tế của hàm FORMAT. 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 thấy trình dọn dẹp hàm FORMAT không hiệu quả về mặt thời gian thực hiện. Bảng Tally tôi sử dụng có 64.000 hồ sơ. Kudos cho 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 hiện máy chủ SQL: 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
Thời gian thực thi máy chủ SQL:
Thời gian CPU = 31 ms, thời gian trôi qua = 235 ms.
Có lẽ giết chết tôi có các UDF này để chuyển sang 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))+@var
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
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 về độ dài hoặc ký tự đệm, sẽ là (giả sử rằng bạn muốn đệm nó với " 0 "đến 10 ký tự:
DECLARE
@pad_characters VARCHAR(10)
SET @pad_characters = '0000000000'
SELECT RIGHT(@pad_characters + @str, 10)
có lẽ quá mức cần thiết, tôi thường sử dụng UDF này:
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
Để bạn có thể làm những việc như:
select dbo.f_pad_before('aaa', 10, '_')
Đây là một cách đơn giản để đệm trái:
REPLACE(STR(FACT_HEAD.FACT_NO, x, 0), ' ', y)
Trong trường hợp x
là số pad và y
là nhân vật pad.
mẫu vật:
REPLACE(STR(FACT_HEAD.FACT_NO, 3, 0), ' ', 0)
1
trở thành 001
.
select right(replicate(@padchar, @len) + @str, @len)
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ư ký tự đệm mặc định nếu 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
Lập trình viên / Chuyên viên phân tích Hiệu trưởng I
Đơn vị kinh doanh Trợ cấp y tế
Đây là giải pháp của tôi, giúp tránh các chuỗi bị cắt cụt và sử dụng SQL đơn giản. Cảm ơn @AlexCuse , @Kevin và @Sklivvz , mà 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]=@longestStringValue, [@maxLengthOfPaddedString]=@maxLengthOfPaddedString;
-- 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 biết điều này không thêm nhiều vào cuộc trò chuyện vào thời điểm này nhưng tôi đang chạy một quy trình tạo tệp và nó sẽ diễn ra rất chậm. Tôi đã sử dụng bản sao và thấy phương pháp cắt này và hình dung tôi sẽ cho nó một shot.
Bạn có thể thấy trong mã của tôi, nơi chuyển đổi giữa hai bên ngoài biến @padding mới (và giới hạn hiện tồn tại). Tôi đã chạy thủ tục của mình với hàm ở cả hai trạng thái có cùng kết quả trong thời gian thực hiện. Vì vậy, ít nhất là trong SQLServer2016, tôi không thấy bất kỳ sự khác biệt nào về hiệu quả mà người khác tìm thấy.
Dù sao, đây là UDF của tôi mà tôi đã viết cách đây nhiều năm cộng với những thay đổi ngày nay giống với những thay đổi khác không phải là tùy chọn LEFT / RIGHT và kiểm tra lỗi.
CREATE FUNCTION PadStringTrim
(
@inputStr varchar(500),
@finalLength int,
@padChar varchar (1),
@padSide varchar(1)
)
RETURNS VARCHAR(500)
AS BEGIN
-- the point of this function is to avoid using replicate which is extremely slow in SQL Server
-- to get away from this though we now have a limitation of how much padding we can add, so I've settled on a hundred character pad
DECLARE @padding VARCHAR (100) = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
SET @padding = REPLACE(@padding, 'X', @padChar)
SET @inputStr = RTRIM(LTRIM(@inputStr))
IF LEN(@inputStr) > @finalLength
RETURN '!ERROR!' -- can search for ! in the returned text
ELSE IF(@finalLength > LEN(@inputStr))
IF @padSide = 'L'
SET @inputStr = RIGHT(@padding + @inputStr, @finalLength)
--SET @inputStr = REPLICATE(@padChar, @finalLength - LEN(@inputStr)) + @inputStr
ELSE IF @padSide = 'R'
SET @inputStr = LEFT(@inputStr + @padding, @finalLength)
--SET @inputStr = @inputStr + REPLICATE(@padChar, @finalLength - LEN(@inputStr))
-- if LEN(@inputStr) = @finalLength we just return it
RETURN @inputStr;
END
-- SELECT dbo.PadStringTrim( tblAccounts.account, 20, '~' , 'R' ) from tblAccounts
-- SELECT dbo.PadStringTrim( tblAccounts.account, 20, '~' , 'L' ) from tblAccounts
Tôi có một chức năng mà lpad có x số thập phân: CREATE FUNCTION [dbo]. [LPAD_DEC] (- Thêm các tham số cho chức năng ở đây @pad nvarchar (MAX), @opes nvarchar (MAX), @length int, @dec int ) TRẢ LẠI nvarchar (tối đa) NHƯ BEGIN - Khai báo biến trả về ở đây DECLARE @resp nvarchar (max)
IF LEN(@string)=@length
BEGIN
IF CHARINDEX('.',@string)>0
BEGIN
SELECT @resp = CASE SIGN(@string)
WHEN -1 THEN
-- Nros negativos grandes con decimales
concat('-',SUBSTRING(replicate(@pad,@length),1,@length-len(@string)),ltrim(str(abs(@string),@length,@dec)))
ELSE
-- Nros positivos grandes con decimales
concat(SUBSTRING(replicate(@pad,@length),1,@length-len(@string)),ltrim(str(@string,@length,@dec)))
END
END
ELSE
BEGIN
SELECT @resp = CASE SIGN(@string)
WHEN -1 THEN
--Nros negativo grande sin decimales
concat('-',SUBSTRING(replicate(@pad,@length),1,(@length-3)-len(@string)),ltrim(str(abs(@string),@length,@dec)))
ELSE
-- Nros positivos grandes con decimales
concat(SUBSTRING(replicate(@pad,@length),1,@length-len(@string)),ltrim(str(@string,@length,@dec)))
END
END
END
ELSE
IF CHARINDEX('.',@string)>0
BEGIN
SELECT @resp =CASE SIGN(@string)
WHEN -1 THEN
-- Nros negativos con decimales
concat('-',SUBSTRING(replicate(@pad,@length),1,@length-len(@string)),ltrim(str(abs(@string),@length,@dec)))
ELSE
--Ntos positivos con decimales
concat(SUBSTRING(replicate(@pad,@length),1,@length-len(@string)),ltrim(str(abs(@string),@length,@dec)))
END
END
ELSE
BEGIN
SELECT @resp = CASE SIGN(@string)
WHEN -1 THEN
-- Nros Negativos sin decimales
concat('-',SUBSTRING(replicate(@pad,@length-3),1,(@length-3)-len(@string)),ltrim(str(abs(@string),@length,@dec)))
ELSE
-- Nros Positivos sin decimales
concat(SUBSTRING(replicate(@pad,@length),1,(@length-3)-len(@string)),ltrim(str(abs(@string),@length,@dec)))
END
END
RETURN @resp
KẾT THÚC
Để cung cấp các giá trị số được làm tròn đến hai chữ số thập phân nhưng được đệ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 hơn, điều đó sẽ được đánh giá cao - những điều trên có vẻ vụng về .
Lưu ý : trong trường hợp này, tôi đang sử dụng SQL Server để gửi email báo cáo ở định dạng HTML và vì vậy muốn định dạng thông tin mà không cần một công cụ bổ sung để phân tích dữ liệu.
Đây là cách tôi thường đệm một varchar
WHILE Len(@String) < 8
BEGIN
SELECT @String = '0' + @String
END