言うと比較して:
REPLICATE(@padchar, @len - LEN(@str)) + @str
どのようにしても、これは単にSQLの非効率的な使い方です。
おそらく何かのような
right('XXXXXXXXXXXX'+ rtrim(@str), @n)
ここで、Xは埋め込み文字、@ nは結果の文字列の文字数です(固定長を扱うために埋め込みが必要であると仮定します)。
しかし、私が言ったようにあなたのデータベースでこれを実際にやるべきではないはずです。
これはもともと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。
何人かの人々がこれのバージョンを与えました:
right('XXXXXXXXXXXX'+ @str, @n)
nより長い場合は実際のデータが切り捨てられるので注意してください。
@padstr = REPLICATE(@padchar, @len) -- this can be cached, done only once
SELECT RIGHT(@padstr + @str, @len)
おそらく私はこれらの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
私があなたが与える方法が本当に非効率的であるかどうかはわかりませんが、長さやパディング文字の点で柔軟である必要がない限り、別の方法があります。 0 "〜10文字
DECLARE
@pad_characters VARCHAR(10)
SET @pad_characters = '0000000000'
SELECT RIGHT(@pad_characters + @str, 10)
私は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
おそらくやり過ぎで、私はよくこの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, '_')
これは左詰めする簡単な方法です:
REPLACE(STR(FACT_HEAD.FACT_NO, x, 0), ' ', y)
x
は埋め込み番号、y
は埋め込み文字です。
サンプル:
REPLACE(STR(FACT_HEAD.FACT_NO, 3, 0), ' ', 0)
select right(replicate(@padchar, @len) + @str, @len)
SQL Server 2005以降では、これを行うためにCLR関数を作成できました。
これが誰かに役立つことを願っています。
STUFF ( character_expression , start , length ,character_expression )
select stuff(@str, 1, 0, replicate('0', @n - len(@str)))
これはどう:
replace((space(3 - len(MyField))
3はパディングするzeros
の数です
10進数xでlpadする関数が1つあります。CREATEFUNCTION [dbo]。[LPAD_DEC](-関数のパラメーターをここに追加します@pad nvarchar(MAX)、@ string nvarchar(MAX)、@ length int、@ dec int )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
終わり
私はこれを使います。デフォルトのパディング文字が提供されていない場合は、それを使用して結果の長さを決定することもできます。もちろん、実行する最大値に合わせて入力と出力の長さをカスタマイズできます。
/*===============================================================
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メディケイド事業部
私はこれがこの時点で会話に多くを追加していないことを知っていますが、私はファイル生成手順を実行していて、それは信じられないほど遅いです。私はレプリケートを使っていて、このトリム方法を見て、私はそれに打撃を与えたいと考えました。
私のコードでは、2つの間の切り替えが新しい@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
これが私の解決策で、切り捨てられた文字列を避け、普通の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;