与之相比:
REPLICATE(@padchar, @len - LEN(@str)) + @str
答案 0 :(得分:318)
无论您如何操作,这只是SQL的低效使用。
或许类似
right('XXXXXXXXXXXX'+ rtrim(@str), @n)
其中X是您的填充字符,@ n是结果字符串中的字符数(假设您需要填充,因为您正在处理固定长度)。
但正如我所说,你应该真的避免在你的数据库中这样做。
答案 1 :(得分:52)
我知道这最初是在2008年被问到的,但是SQL Server 2012引入了一些新的功能。FORMAT function很好地简化了填充左边的填充。它还会为您执行转换:
declare @n as int = 2
select FORMAT(@n, 'd10') as padWithZeros
<强>更新强>
我想亲自测试FORMAT功能的实际效率。我很惊讶地发现,与AlexCuse的原始答案相比,效率并不是很好。虽然我发现FORMAT功能更清洁,但在执行时间方面效率不高。我使用的Tally表有64,000条记录。感谢Martin Smith指出执行时间的效率。
SET STATISTICS TIME ON
select FORMAT(N, 'd10') as padWithZeros from Tally
SET STATISTICS TIME OFF
SQL Server执行时间: CPU时间= 2157毫秒,经过时间= 2696毫秒。
SET STATISTICS TIME ON
select right('0000000000'+ rtrim(cast(N as varchar(5))), 10) from Tally
SET STATISTICS TIME OFF
SQL Server执行时间:
CPU时间= 31 ms,经过时间= 235 ms。
答案 2 :(得分:35)
有几个人给出了这个版本:
right('XXXXXXXXXXXX'+ @str, @n)
要小心,因为如果它长于n,它会截断你的实际数据。
答案 3 :(得分:16)
@padstr = REPLICATE(@padchar, @len) -- this can be cached, done only once
SELECT RIGHT(@padstr + @str, @len)
答案 4 :(得分:9)
也许过度杀戮我有这些UDF左右填充
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
到右边
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
答案 5 :(得分:6)
我不确定你给出的方法效率是否低效,但是另一种方法是,只要它不必在长度或填充字符中具有灵活性,就会(假设你想要填充)它用“0”到10个字符:
DECLARE
@pad_characters VARCHAR(10)
SET @pad_characters = '0000000000'
SELECT RIGHT(@pad_characters + @str, 10)
答案 6 :(得分:2)
我喜欢vnRocks解决方案,这里的形式是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
答案 7 :(得分:2)
可能有点过分,我经常使用这个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
这样你就可以做到:
select dbo.f_pad_before('aaa', 10, '_')
答案 8 :(得分:2)
这是一个简单的填充方法:
REPLACE(STR(FACT_HEAD.FACT_NO, x, 0), ' ', y)
其中x
是填充编号,y
是填充字符。
样品:
REPLACE(STR(FACT_HEAD.FACT_NO, 3, 0), ' ', 0)
答案 9 :(得分:1)
我希望这有助于某人。
STUFF ( character_expression , start , length ,character_expression )
select stuff(@str, 1, 0, replicate('0', @n - len(@str)))
答案 10 :(得分:1)
这个怎么样:
replace((space(3 - len(MyField))
3是填充zeros
的数量
答案 11 :(得分:1)
在SQL Server 2005及更高版本中,您可以创建一个CLR函数来执行此操作。
答案 12 :(得分:1)
select right(replicate(@padchar, @len) + @str, @len)
答案 13 :(得分:0)
我用这个。它允许您确定结果的长度以及默认填充字符(如果未提供)。当然,无论您遇到什么最大值,您都可以自定义输入和输出的长度。
/*===============================================================
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
您的里程可能会有所不同。 :-)
乔伊摩根士
程序员/分析师校长I
WellPoint医疗补助业务部门
答案 14 :(得分:0)
这是我的解决方案,它可以避免截断字符串并使用普通字符串&#39; SQL。感谢 @AlexCuse , @Kevin 和 @Sklivvz ,其解决方案是此代码的基础。
--[@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;
答案 15 :(得分:0)
我知道这在当前对话中并没有增加太多,但是我正在运行文件生成过程,并且执行过程非常缓慢。我一直在使用复制,并看到了这种修整方法,然后想出了办法。
您可以在我的代码中看到除了新的@padding变量(以及现在存在的限制)之外,两者之间的切换。我在两种状态下都使用该函数运行了过程,并且执行时间相同。因此,至少在SQLServer2016中,我没有看到其他人发现的效率差异。
无论如何,这是我几年前写的UDF,加上今天的更改,与其他更改相同,除了具有LEFT / RIGHT参数选项和一些错误检查之外。
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
答案 16 :(得分:0)
我有一个用x小数表示lpad的函数: 创建功能[dbo]。[LPAD_DEC] ( -在此处添加函数的参数 @pad nvarchar(MAX), @string nvarchar(MAX), @length int, @dec int ) 返回nvarchar(max) 如 开始 -在这里声明返回变量 声明@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
END
答案 17 :(得分:0)
这是我的解决方案。我可以填充任何字符,而且速度很快。简单地去了。您可以更改大小来满足您的需求。
使用参数更新以处理如果为null时返回的内容:如果为null,则null将返回null
CREATE OR ALTER FUNCTION code.fnConvert_PadLeft(
@in_str nvarchar(1024),
@pad_length int,
@pad_char nchar(1) = ' ',
@rtn_null NVARCHAR(1024) = '')
RETURNS NVARCHAR(1024)
AS
BEGIN
DECLARE @rtn NCHAR(1024) = ' '
RETURN RIGHT(REPLACE(@rtn,' ',@pad_char)+ISNULL(@in_str,@rtn_null), @pad_length)
END
GO
CREATE OR ALTER FUNCTION code.fnConvert_PadRight(
@in_str nvarchar(1024),
@pad_length int,
@pad_char nchar(1) = ' ',
@rtn_null NVARCHAR(1024) = '')
RETURNS NVARCHAR(1024)
AS
BEGIN
DECLARE @rtn NCHAR(1024) = ' '
RETURN LEFT(ISNULL(@in_str,@rtn_null)+REPLACE(@rtn,' ',@pad_char), @pad_length)
END
GO
-- Example
SET STATISTICS time ON
SELECT code.fnConvert_PadLeft('88',10,'0',''),
code.fnConvert_PadLeft(null,10,'0',''),
code.fnConvert_PadLeft(null,10,'0',null),
code.fnConvert_PadRight('88',10,'0',''),
code.fnConvert_PadRight(null,10,'0',''),
code.fnConvert_PadRight(null,10,'0',NULL)
0000000088 0000000000 NULL 8800000000 0000000000 NULL
答案 18 :(得分:-1)
提供四舍五入到小数点后两位的数字值,但如果需要,用零填充右边:
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)
如果有人能想到更简洁的方式,那将是值得赞赏的 - 上面似乎笨拙。
注意:在这个例子中,我使用SQL Server以HTML格式发送报告,因此希望格式化信息,而不需要额外的工具来解析数据。
答案 19 :(得分:-4)
以下是我通常填充varchar的方法
WHILE Len(@String) < 8
BEGIN
SELECT @String = '0' + @String
END