Відповіді:
Це просто неефективне використання SQL, незалежно від того, як ви це зробите.
можливо, щось подібне
right('XXXXXXXXXXXX'+ rtrim(@str), @n)
де X - ваш символ прокладки, а @n - кількість символів у отриманій рядку (якщо припустити, що вам потрібна накладка, оскільки ви маєте справу з фіксованою довжиною).
Але, як я вже сказав, вам слід уникати цього робити у своїй базі даних.
RTRIM(@str)якщо це може містити пробіли.
Я знаю, що це спочатку запитували ще в 2008 році, але є деякі нові функції, які були введені у програмі SQL Server 2012. Функція FORMAT спрощує прокладку, залишену нулями. Він також здійснить перетворення для вас:
declare @n as int = 2
select FORMAT(@n, 'd10') as padWithZeros
Оновлення:
Я хотів сам перевірити фактичну ефективність функції FORMAT. Я був дуже здивований, коли виявив, що ефективність була не дуже хорошою порівняно з оригінальною відповіддю від AlexCuse . Хоча я вважаю, що функція FORMAT чистіша, вона не дуже ефективна з точки зору часу виконання. Таблиця Tally, яку я використав, має 64 000 записів. Кудос Мартіну Сміту за вказівку на ефективність виконання часу.
SET STATISTICS TIME ON
select FORMAT(N, 'd10') as padWithZeros from Tally
SET STATISTICS TIME OFF
Часи виконання SQL Server: час процесора = 2157 мс, минулий час = 2696 мс.
SET STATISTICS TIME ON
select right('0000000000'+ rtrim(cast(N as varchar(5))), 10) from Tally
SET STATISTICS TIME OFF
Часи виконання SQL Server:
Час процесора = 31 мс, минулий час = 235 мс.
Можливо, надмірне вбивство у мене є ці АДС, щоб прокладати ліворуч та праворуч
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)
ймовірно, надмірність, я часто використовую цей 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)
1стають 001.
select right(replicate(@padchar, @len) + @str, @len)
Я використовую цей. Це дозволяє визначити довжину, яку ви хочете, щоб результат був, а також символ прокладки за замовчуванням, якщо такий не вказаний. Звичайно, ви можете налаштувати довжину вводу та виходу для будь-яких максимумів, з якими ви стикаєтесь.
/*===============================================================
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
Програміст / аналітик, директор I
WellPoint Medicaid Business Unit
Ось моє рішення, яке уникає усічених рядків і використовує звичайний ol '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;
Я знаю, що це не додає багато розмови на даний момент, але я запускаю процедуру генерації файлів, і це відбувається дуже повільно. Я використовував репліку і бачив цей метод обрізки і подумав, що я б його сфотографував.
У моєму коді ви бачите, де перемикання між цими двома є додатково до нової змінної @padding (і обмеження, яке зараз існує). Я запустив свою процедуру з функцією в обох станах з однаковими результатами у часі виконання. Так що, принаймні, у SQLServer2016 я не бачу різниці в ефективності, яку знайшли інші.
У будь-якому випадку, ось мій UDF, про який я писав роки тому, а також зміни, які сьогодні такі ж, як і інші, ніж інші, мають параметр Вліво / Вправо парам і деякі перевірки помилок.
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
У мене є одна функція, яка lpad з x десятковими знаками: CREATE FUNCTION [dbo]. [LPAD_DEC] (- Додайте сюди параметри функції @pad nvarchar (MAX), @string nvarchar (MAX), @length int, @dec int ) ПОВЕРНУТИСЯ nvarchar (max) ЯК ПОЧАТО - оголосити тут змінну повернення 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
Кінець
Щоб надати числові значення, округлені до двох знаків після коми, але праворуч зафіксовані нулями, якщо потрібно, я маю:
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, тому хочу відформатувати інформацію, не використовуючи додатковий інструмент для аналізу даних.