Yanıtlar:
Bu, nasıl yaparsanız yapın, SQL'in verimsiz bir kullanımıdır.
belki böyle bir şey
right('XXXXXXXXXXXX'+ rtrim(@str), @n)
burada X, doldurma karakteriniz ve @n, elde edilen dizgideki karakter sayısıdır (sabit bir uzunlukla uğraştığınız için dolguya ihtiyacınız olduğu varsayılarak).
Ama dediğim gibi bunu gerçekten veritabanınızda yapmaktan kaçınmalısınız.
RTRIM(@str)
Yine de bu sondaki boşluklar içeriyorsa, yapmanız gerekebilir .
Bunun 2008'de geri istendiğini biliyorum, ancak SQL Server 2012 ile tanıtılan bazı yeni işlevler var. FORMAT işlevi sıfırlarla güzelce bırakılan dolguları basitleştirir. Ayrıca sizin için dönüşüm gerçekleştirir:
declare @n as int = 2
select FORMAT(@n, 'd10') as padWithZeros
Güncelleme:
FORMAT işlevinin gerçek verimliliğini kendim test etmek istedim. AlexCuse'un orijinal cevabına göre verimliliğin çok iyi olmadığını bulmak oldukça şaşırdım . FORMAT işlevini daha temiz bulmama rağmen, yürütme süresi açısından çok verimli değil. Kullandığım Tally tablosunda 64.000 kayıt var. Yürütme zamanı verimliliğine dikkat çektiği için Martin Smith'e şeref .
SET STATISTICS TIME ON
select FORMAT(N, 'd10') as padWithZeros from Tally
SET STATISTICS TIME OFF
SQL Server Yürütme Süreleri: CPU süresi = 2157 ms, geçen süre = 2696 ms.
SET STATISTICS TIME ON
select right('0000000000'+ rtrim(cast(N as varchar(5))), 10) from Tally
SET STATISTICS TIME OFF
SQL Server Yürütme Süreleri:
CPU süresi = 31 ms, geçen süre = 235 ms.
Belki de aşırı öldürme bu UDF'leri sağa ve sola doldurmak için kullanıyorum
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
ve sağa
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
Verdiğiniz yöntemin gerçekten verimsiz olduğundan emin değilim, ancak uzunluk veya dolgu karakterinde esnek olması gerekmediği sürece alternatif bir yol (" 0 "- 10 karakter arası:
DECLARE
@pad_characters VARCHAR(10)
SET @pad_characters = '0000000000'
SELECT RIGHT(@pad_characters + @str, 10)
muhtemelen aşırıya kaçma, ben genellikle bu UDF kullanın:
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öylece aşağıdakileri yapabilirsiniz:
select dbo.f_pad_before('aaa', 10, '_')
sola yaslanmanın basit bir yolu:
REPLACE(STR(FACT_HEAD.FACT_NO, x, 0), ' ', y)
x
Pad numarası ve y
pad karakteri nerede .
örneklem:
REPLACE(STR(FACT_HEAD.FACT_NO, 3, 0), ' ', 0)
1
olur 001
.
select right(replicate(@padchar, @len) + @str, @len)
Bunu kullanıyorum. Sonucun olmasını istediğiniz uzunluğu ve sağlanmamışsa varsayılan dolgu karakterini belirlemenizi sağlar. Elbette, giriş ve çıkışın uzunluğunu, çalıştığınız maksimum değerlere göre özelleştirebilirsiniz.
/*===============================================================
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
Kilometreniz değişebilir. :-)
Joey Morgan
Programcı / Analist Müdürü I
WellPoint Medicaid İş Birimi
İşte benim kesilmiş dizeleri önler ve düz ol 'SQL kullanan benim çözüm. Çözümleri bu kodun temeli olan @AlexCuse , @Kevin ve @Sklivvz sayesinde .
--[@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;
Bu, bu noktada konuşmaya fazla bir şey eklemediğini biliyorum ama bir dosya oluşturma prosedürü çalıştırıyorum ve inanılmaz derecede yavaş gidiyor. Replikat kullanıyorum ve bu trim yöntemini gördüm ve bir şans vereceğimi düşündüm.
Kodumda, yeni @padding değişkenine (ve şu anda var olan sınırlamaya) ek olarak ikisi arasındaki geçişin nerede olduğunu görebilirsiniz. Prosedürümü her iki durumda da işlevle aynı zamanda yürütme süresinde çalıştırdım. En azından SQLServer2016'da, diğerlerinin bulduğu verimlilikte herhangi bir fark görmüyorum.
Her neyse, işte yıllar önce yazdığım UDF'm artı bugün bir LEFT / RIGHT param seçeneği ve bazı hata kontrolleri dışında diğerleriyle aynı olan değişiklikler.
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
Ben x ondalık ile lpad bir işlevi var: CREATE FUNCTION [dbo]. [LPAD_DEC] (- Bu işlev için parametreleri ekleyin @pad nvarchar (MAX), @string nvarchar (MAX), @length int, @dec int ) GERİ DÖN nvarchar (maks.) BAŞLANGIÇ - Dönüş değişkenini burada bildirin DECLARE @resp nvarchar (maks.)
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
SON
İki ondalık basamağa yuvarlanmış ancak gerekirse sıfırlarla sağlanmış sayısal değerler sağlamak için:
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)
Herkes daha temiz bir yol düşünebiliyorsa, bu takdir edilecektir - yukarıda sakar görünüyor .
Not : Bu örnekte, raporları HTML biçiminde e-postayla göndermek için SQL Server kullanıyorum ve bu nedenle verileri ayrıştırmak için ek bir araç içermeden bilgileri biçimlendirmek istiyorum.
İşte normalde bir varchar nasıl
WHILE Len(@String) < 8
BEGIN
SELECT @String = '0' + @String
END