Jawaban:
Ini hanyalah penggunaan SQL yang tidak efisien, tidak peduli bagaimana Anda melakukannya.
mungkin sesuatu seperti
right('XXXXXXXXXXXX'+ rtrim(@str), @n)
di mana X adalah karakter padding Anda dan @n adalah jumlah karakter dalam string yang dihasilkan (dengan asumsi Anda membutuhkan padding karena Anda berurusan dengan panjang tetap).
Tetapi seperti yang saya katakan Anda harus benar-benar menghindari melakukan ini di database Anda.
RTRIM(@str)
apakah itu bisa mengandung spasi tambahan.
Saya tahu ini awalnya diminta kembali pada tahun 2008, tetapi ada beberapa fungsi baru yang diperkenalkan dengan SQL Server 2012. Fungsi FORMAT menyederhanakan bantalan kiri dengan nol dengan baik. Itu juga akan melakukan konversi untuk Anda:
declare @n as int = 2
select FORMAT(@n, 'd10') as padWithZeros
Memperbarui:
Saya ingin menguji sendiri efisiensi fungsi FORMAT. Saya cukup terkejut menemukan efisiensi tidak terlalu baik dibandingkan dengan jawaban asli dari AlexCuse . Meskipun saya menemukan fungsi FORMAT lebih bersih, tidak terlalu efisien dalam hal waktu eksekusi. Tabel Tally yang saya gunakan memiliki 64.000 catatan. Kudos to Martin Smith untuk menunjukkan efisiensi waktu eksekusi.
SET STATISTICS TIME ON
select FORMAT(N, 'd10') as padWithZeros from Tally
SET STATISTICS TIME OFF
Waktu Eksekusi SQL Server: Waktu CPU = 2157 ms, waktu yang berlalu = 2696 ms.
SET STATISTICS TIME ON
select right('0000000000'+ rtrim(cast(N as varchar(5))), 10) from Tally
SET STATISTICS TIME OFF
Waktu Eksekusi SQL Server:
Waktu CPU = 31 ms, waktu yang berlalu = 235 ms.
Mungkin over-kill, saya punya UDF ini di sebelah kiri dan kanan
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
dan ke kanan
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
Saya tidak yakin metode yang Anda berikan benar-benar tidak efisien, tetapi cara alternatif, asalkan tidak harus fleksibel dalam panjang atau karakter padding, akan menjadi (dengan asumsi bahwa Anda ingin menambahkannya dengan " 0 "hingga 10 karakter:
DECLARE
@pad_characters VARCHAR(10)
SET @pad_characters = '0000000000'
SELECT RIGHT(@pad_characters + @str, 10)
mungkin berlebihan, saya sering menggunakan UDF ini:
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
Sehingga Anda dapat melakukan hal-hal seperti:
select dbo.f_pad_before('aaa', 10, '_')
ini adalah cara sederhana untuk menulis kiri:
REPLACE(STR(FACT_HEAD.FACT_NO, x, 0), ' ', y)
Di mana x
nomor pad dan y
karakter pad.
Sampel:
REPLACE(STR(FACT_HEAD.FACT_NO, 3, 0), ' ', 0)
1
menjadi 001
.
select right(replicate(@padchar, @len) + @str, @len)
Saya menggunakan yang ini. Ini memungkinkan Anda untuk menentukan panjang yang Anda inginkan hasilnya serta karakter padding default jika tidak disediakan. Tentu saja Anda dapat menyesuaikan panjang input dan output untuk berapa pun maksimum yang Anda temui.
/*===============================================================
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
Jarak tempuh Anda mungkin beragam. :-)
Joey Morgan
Programmer / Analis Kepala I
Unit Bisnis Medicaid I WellPoint
Inilah solusi saya, yang menghindari string terpotong dan menggunakan SQL sederhana. Berkat @AlexCuse , @ Kevin dan @Sklivvz , yang solusi adalah dasar dari kode ini.
--[@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;
Saya tahu ini tidak menambah banyak percakapan pada saat ini, tetapi saya sedang menjalankan prosedur pembuatan file dan itu akan sangat lambat. Saya telah menggunakan replikat dan melihat metode trim ini dan berpikir saya akan mencobanya.
Anda dapat melihat dalam kode saya di mana pergantian di antara keduanya merupakan tambahan pada variabel @padding baru (dan batasan yang sekarang ada). Saya menjalankan prosedur saya dengan fungsi di kedua negara dengan hasil yang sama dalam waktu eksekusi. Jadi setidaknya di SQLServer2016, saya tidak melihat perbedaan dalam efisiensi yang ditemukan orang lain.
Ngomong-ngomong, ini UDF saya yang saya tulis bertahun-tahun yang lalu ditambah perubahan hari ini yang sama seperti yang lain selain memiliki opsi param KIRI / KANAN dan beberapa pengecekan kesalahan.
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
Saya punya satu fungsi yang lpad dengan x desimal: CREATE FUNCTION [dbo]. [LPAD_DEC] (- Tambahkan parameter untuk fungsi di sini @pad nvarchar (MAX), @string nvarchar (MAX), @length int, @dec int ) RETURNS nvarchar (maks) AS BEGIN - Deklarasikan variabel return di sini 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
AKHIR
Untuk memberikan nilai numerik dibulatkan ke dua tempat desimal tetapi diisi dengan nol jika diperlukan, saya harus:
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)
Jika ada yang bisa memikirkan cara yang lebih rapi, itu akan dihargai - hal di atas nampak canggung .
Catatan : dalam contoh ini, saya menggunakan SQL Server untuk mengirim email laporan dalam format HTML dan ingin memformat informasi tanpa melibatkan alat tambahan untuk mengurai data.
Ini adalah bagaimana saya biasanya membuat varchar
WHILE Len(@String) < 8
BEGIN
SELECT @String = '0' + @String
END