Antworten:
Dies ist einfach eine ineffiziente Verwendung von SQL, egal wie Sie es tun.
vielleicht so etwas wie
right('XXXXXXXXXXXX'+ rtrim(@str), @n)
Dabei ist X Ihr Auffüllzeichen und @n die Anzahl der Zeichen in der resultierenden Zeichenfolge (vorausgesetzt, Sie benötigen das Auffüllen, weil Sie es mit einer festen Länge zu tun haben).
Aber wie gesagt, Sie sollten dies in Ihrer Datenbank wirklich vermeiden.
RTRIM(@str)
tun, wenn dies nachgestellte Leerzeichen enthalten kann.
Ich weiß, dass dies ursprünglich im Jahr 2008 gefragt wurde, aber es gibt einige neue Funktionen, die mit SQL Server 2012 eingeführt wurden. Die FORMAT-Funktion vereinfacht das Auffüllen mit Nullen. Es wird auch die Konvertierung für Sie durchführen:
declare @n as int = 2
select FORMAT(@n, 'd10') as padWithZeros
Aktualisieren:
Ich wollte die tatsächliche Effizienz der FORMAT-Funktion selbst testen. Ich war ziemlich überrascht, dass die Effizienz im Vergleich zur ursprünglichen Antwort von AlexCuse nicht sehr gut war . Obwohl ich die FORMAT-Funktion sauberer finde, ist sie in Bezug auf die Ausführungszeit nicht sehr effizient. Die von mir verwendete Tally-Tabelle enthält 64.000 Datensätze. Ein großes Lob an Martin Smith für den Hinweis auf die Effizienz der Ausführungszeit.
SET STATISTICS TIME ON
select FORMAT(N, 'd10') as padWithZeros from Tally
SET STATISTICS TIME OFF
SQL Server-Ausführungszeiten: CPU-Zeit = 2157 ms, verstrichene Zeit = 2696 ms.
SET STATISTICS TIME ON
select right('0000000000'+ rtrim(cast(N as varchar(5))), 10) from Tally
SET STATISTICS TIME OFF
SQL Server-Ausführungszeiten:
CPU-Zeit = 31 ms, verstrichene Zeit = 235 ms.
Vielleicht ein Over-Kill Ich habe diese UDFs, um links und rechts aufzufüllen
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
und nach rechts
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
Ich bin mir nicht sicher, ob die von Ihnen angegebene Methode wirklich ineffizient ist, aber eine alternative Methode, sofern sie nicht in der Länge oder im Auffüllcharakter flexibel sein muss, wäre (vorausgesetzt, Sie möchten sie auffüllen ". 0 "bis 10 Zeichen:
DECLARE
@pad_characters VARCHAR(10)
SET @pad_characters = '0000000000'
SELECT RIGHT(@pad_characters + @str, 10)
wahrscheinlich übertrieben, ich benutze oft diese 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
Damit Sie Dinge tun können wie:
select dbo.f_pad_before('aaa', 10, '_')
Dies ist eine einfache Möglichkeit, links aufzufüllen:
REPLACE(STR(FACT_HEAD.FACT_NO, x, 0), ' ', y)
Wo x
ist die Pad-Nummer undy
ist das Pad-Zeichen.
Stichprobe:
REPLACE(STR(FACT_HEAD.FACT_NO, 3, 0), ' ', 0)
1
wird 001
.
select right(replicate(@padchar, @len) + @str, @len)
Ich benutze diesen. Hier können Sie die Länge bestimmen, in der das Ergebnis angezeigt werden soll, sowie ein Standard-Füllzeichen, falls keines angegeben ist. Natürlich können Sie die Länge der Ein- und Ausgabe für jedes Maximum anpassen, auf das Sie stoßen.
/*===============================================================
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
Ihr Kilometerstand kann variieren. :-)
Joey Morgan
Programmierer / Analyst Principal I
Geschäftsbereich WellPoint Medicaid
Hier ist meine Lösung, die abgeschnittene Zeichenfolgen vermeidet und einfaches altes SQL verwendet. Vielen Dank an @AlexCuse , @Kevin und @Sklivvz , deren Lösungen die Grundlage dieses Codes bilden.
--[@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;
Ich weiß, dass dies zu diesem Zeitpunkt nicht viel zur Konversation beiträgt, aber ich führe eine Prozedur zur Dateierzeugung aus, die unglaublich langsam verläuft. Ich habe Replikat verwendet und diese Trimmmethode gesehen und dachte, ich würde es versuchen.
Sie können in meinem Code sehen, wo der Wechsel zwischen den beiden zusätzlich zu der neuen @ padding-Variablen (und der jetzt bestehenden Einschränkung) erfolgt. Ich habe meine Prozedur mit der Funktion in beiden Zuständen mit den gleichen Ergebnissen in der Ausführungszeit ausgeführt. Zumindest in SQLServer2016 sehe ich keinen Unterschied in der Effizienz, den andere festgestellt haben.
Wie auch immer, hier ist meine UDF, die ich vor Jahren geschrieben habe, sowie die Änderungen heute, die denen anderer sehr ähnlich sind, außer dass sie eine LINKS / RECHTS-Parameteroption und einige Fehlerprüfungen enthalten.
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
Ich habe eine Funktion, die mit x Dezimalstellen lpad: CREATE FUNCTION [dbo]. [LPAD_DEC] (- Fügen Sie hier die Parameter für die Funktion hinzu @pad nvarchar (MAX), @string nvarchar (MAX), @length int, @dec int ) RETURNS nvarchar (max) AS BEGIN - Deklarieren Sie die Rückgabevariable hier 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
ENDE
Um numerische Werte bereitzustellen, die auf zwei Dezimalstellen gerundet, aber bei Bedarf mit Nullen rechts aufgefüllt sind, habe ich:
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)
Wenn sich jemand einen ordentlicheren Weg vorstellen kann, wäre das wünschenswert - das oben Gesagte scheint ungeschickt zu sein .
Hinweis : In diesem Fall verwende ich SQL Server, um Berichte im HTML-Format per E-Mail zu versenden, und möchte daher die Informationen formatieren, ohne ein zusätzliches Tool zum Parsen der Daten zu verwenden.
Hier ist, wie ich normalerweise einen Varchar auffüllen würde
WHILE Len(@String) < 8
BEGIN
SELECT @String = '0' + @String
END