211

相比而言:

REPLICATE(@padchar, @len - LEN(@str)) + @str
4

20 回答 20

331

这只是对 SQL 的低效使用,无论您如何操作。

也许像

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

其中 X 是您的填充字符,@n 是结果字符串中的字符数(假设您需要填充,因为您正在处理固定长度)。

但正如我所说,你真的应该避免在你的数据库中这样做。

于 2008-09-23T15:50:14.240 回答
63

我知道这最初是在 2008 年提出的,但是 SQL Server 2012 引入了一些新函数。FORMAT 函数很好地简化了用零填充。它还将为您执行转换:

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 毫秒,经过时间 = 235 毫秒。

于 2014-09-29T19:04:55.400 回答
36

几个人给出了这个版本:

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

请注意这一点,因为如果它长于 n,它将截断您的实际数据。

于 2008-09-26T15:06:33.093 回答
16
@padstr = REPLICATE(@padchar, @len) -- this can be cached, done only once

SELECT RIGHT(@padstr + @str, @len)
于 2008-09-23T15:52:07.793 回答
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
于 2010-06-05T22:18:07.903 回答
8

我不确定您提供的方法是否真的效率低下,但是另一种方法,只要它在长度或填充字符上不必灵活,就可以(假设您想用“ 0" 到 10 个字符:

DECLARE
   @pad_characters VARCHAR(10)

SET @pad_characters = '0000000000'

SELECT RIGHT(@pad_characters + @str, 10)
于 2008-09-23T15:51:27.793 回答
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, '_')
于 2008-09-23T16:01:30.017 回答
2

这是一种向左填充的简单方法:

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

哪里x是焊盘编号,y是焊盘字符。

样本:

REPLACE(STR(FACT_HEAD.FACT_NO, 3, 0), ' ', 0)
于 2010-12-08T15:45:35.743 回答
2

我希望这可以帮助别人。

STUFF ( character_expression , start , length ,character_expression )

select stuff(@str, 1, 0, replicate('0', @n - len(@str)))
于 2011-06-16T13:34:43.850 回答
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
于 2011-10-28T15:11:45.780 回答
1
select right(replicate(@padchar, @len) + @str, @len)
于 2008-09-23T15:54:41.407 回答
1

在 SQL Server 2005 及更高版本中,您可以创建一个 CLR 函数来执行此操作。

于 2008-09-23T15:55:04.027 回答
1

这个怎么样:

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

3 是zeros要填充的数量

于 2009-03-24T16:15:04.577 回答
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

你的旅费可能会改变。:-)

Joey Morgan
程序员/分析师负责人我
WellPoint 医疗补助业务部

于 2013-05-21T20:08:51.120 回答
0

这是我的解决方案,它避免了截断字符串并使用普通的 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;
于 2017-05-25T19:44:37.853 回答
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
于 2019-03-07T01:50:44.827 回答
0

我有一个带有 x 小数的 lpad 函数: CREATE FUNCTION [dbo].[LPAD_DEC] ( -- 在此处添加函数的参数 @pad nvarchar(MAX), @string nvarchar(MAX), @length int, @dec int ) RETURNS nvarchar(max) AS BEGIN -- 在此处声明返回变量 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

结尾

于 2019-08-16T23:46:36.780 回答
0

这是我的解决方案。我可以填充任何字符,而且速度很快。很简单。您可以更改可变大小以满足您的需求。

更新了一个参数来处理 null 时返回的内容: null 将返回 null if 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

于 2020-10-12T15:04:52.213 回答
-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 格式通过电子邮件发送报告,因此希望在不涉及解析数据的其他工具的情况下格式化信息。

于 2012-03-19T00:52:46.200 回答
-4

这是我通常如何填充 varchar

WHILE Len(@String) < 8
BEGIN
    SELECT @String = '0' + @String
END
于 2011-09-21T12:06:54.437 回答