patindex t-sql special characters - sql

How to check if any of this !##$%^&*()_-+ special characters exist in a string ?
i tried
SELECT PATINDEX('!##$%^&*()_-+', 'test-');
SELECT PATINDEX('[!##$%^&*()_-+]', 'test-');
SELECT PATINDEX('%[!##$%^&*()_-+]%', 'test-');
but all returns 0, it should return 5, any help ?

The - is a special character in the LIKE or PATINDEX() pattern. If it is anywhere other than the first position, it is a range of characters -- such as all digits being represented by [0-9].
You can do what you want by moving the condition:
PATINDEX('%[-!##$%^&*()_+]%', 'test-'),
Unfortunately, PATINDEX() patterns don't support an escape character. You can also express this logic as a LIKE and CASE:
(CASE WHEN 'test-' LIKE '%[-!##$%^&*()_+]%' ESCAPE '$' THEN 1 ELSE 0 END)
Or using a "not" pattern:
(CASE WHEN 'test-' NOT LIKE '%[^0-9a-zA-Z]%' THEN 0 ELSE 1 END)

You can use negation:
SELECT PATINDEX('%[^a-Z]%', 'test-');
This will find a character NOT in the range a-Z.

SELECT PATINDEX('%[-+!_#()*^#$%&]%', 'test-');
this solves my issue returns 5 the positon of -.
Apperently order matters.

DECLARE #myString VARCHAR(100) ='test-'
IF (#myString LIKE '%[^a-zA-Z0-9]%')
PRINT 'Contains "special" characters'
ELSE
PRINT 'Does not contain "special" characters'

select patindex('%[' + char(45) + ']%', 'test-');
But symbol '-' not working in range values, replace this symbol on another symbol
Next example find only writable symbols in #string:
declare #string varchar(max) = char(8) + char(9) + char(10) + char(11) + char(12) + char(13) + '-test string-';
select patindex(%[' + char(33) + '-' + char(255) + ']%', replace(#string, '-', '#'))

Related

Using SQL Server to replace line breaks in columns with spaces

I have a large table of data where some of my columns contain line breaks. I would like to remove them and replace them with some spaces instead.
Can anybody tell me how to do this in SQL Server?
Thanks in advance
SELECT REPLACE(REPLACE(#str, CHAR(13), ''), CHAR(10), '')
This should work, depending on how the line breaks are encoded:
update t
set col = replace(col, '
', ' ')
where col like '%
%';
That is, in SQL Server, a string can contain a new line character.
#Gordon's answer should work, but in case you're not sure how your line breaks are encoded, you can use the ascii function to return the character value. For example:
declare #entry varchar(50) =
'Before break
after break'
declare #max int = len(#entry)
; with CTE as (
select 1 as id
, substring(#entry, 1, 1) as chrctr
, ascii(substring(#entry, 1, 1)) as code
union all
select id + 1
, substring(#entry, ID + 1, 1)
, ascii(substring(#entry, ID + 1, 1))
from CTE
where ID <= #max)
select chrctr, code from cte
print replace(replace(#entry, char(13) , ' '), char(10) , ' ')
Depending where your text is coming from, there are different encodings for a line break. In my test string I put the most common.
First I replace all CHAR(10) (Line feed) with CHAR(13) (Carriage return), then all doubled CRs to one CR and finally all CRs to the wanted replace (you want a blank, I put a dot for better visability:
Attention: Switch the output to "text", otherwise you wont see any linebreaks...
DECLARE #text VARCHAR(100)='test single 10' + CHAR(10) + 'test 13 and 10' + CHAR(13) + CHAR(10) + 'test single 13' + CHAR(13) + 'end of test';
SELECT #text
DECLARE #ReplChar CHAR='.';
SELECT REPLACE(REPLACE(REPLACE(#text,CHAR(10),CHAR(13)),CHAR(13)+CHAR(13),CHAR(13)),CHAR(13),#ReplChar);
I have the same issue, means I have a column having values with line breaks in it. I use the query
update `your_table_name` set your_column_name = REPLACE(your_column_name,'\n','')
And this resolves my issue :)
Basically '\n' is the character for Enter key or line break and in this query, I have replaced it with no space (which I want)
Keep Learning :)
zain

Remove only leading or trailing carriage returns

I'm dumbfounded that this question has not been asked meaningfully already. How does one go about creating an equivalent function in SQL like LTRIM or RTRIM for carriage returns and line feeds ONLY at the start or end of a string.
Obviously REPLACE(REPLACE(#MyString,char(10),''),char(13),'') removes ALL carriage returns and new line feeds. Which is NOT what I'm looking for. I just want to remove leading or trailing ones.
Find the first character that is not CHAR(13) or CHAR(10) and subtract its position from the string's length.
LTRIM()
SELECT RIGHT(#MyString,LEN(#MyString)-PATINDEX('%[^'+CHAR(13)+CHAR(10)+']%',#MyString)+1)
RTRIM()
SELECT LEFT(#MyString,LEN(#MyString)-PATINDEX('%[^'+CHAR(13)+CHAR(10)+']%',REVERSE(#MyString))+1)
Following functions are enhanced types of trim functions you can use. Copied from sqlauthority.com
These functions remove trailing spaces, leading spaces, white space, tabs, carriage returns, line feeds etc.
Trim Left
CREATE FUNCTION dbo.LTrimX(#str VARCHAR(MAX)) RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #trimchars VARCHAR(10)
SET #trimchars = CHAR(9)+CHAR(10)+CHAR(13)+CHAR(32)
IF #str LIKE '[' + #trimchars + ']%' SET #str = SUBSTRING(#str, PATINDEX('%[^' + #trimchars + ']%', #str), LEN(#str))
RETURN #str
END
Trim Right
CREATE FUNCTION dbo.RTrimX(#str VARCHAR(MAX)) RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #trimchars VARCHAR(10)
SET #trimchars = CHAR(9)+CHAR(10)+CHAR(13)+CHAR(32)
IF #str LIKE '%[' + #trimchars + ']'
SET #str = REVERSE(dbo.LTrimX(REVERSE(#str)))
RETURN #str
END
Trim both Left and Right
CREATE FUNCTION dbo.TrimX(#str VARCHAR(MAX)) RETURNS VARCHAR(MAX)
AS
BEGIN
RETURN dbo.LTrimX(dbo.RTrimX(#str))
END
Using function
SELECT dbo.TRIMX(#MyString)
If you do use these functions you might also consider changing from varchar to nvarchar to support more encodings.
In SQL Server 2017 you can use the TRIM function to remove specific characters from beginning and end, in one go:
WITH testdata(str) AS (
SELECT CHAR(13) + CHAR(10) + ' test ' + CHAR(13) + CHAR(10)
)
SELECT
str,
TRIM(CHAR(13) + CHAR(10) + CHAR(9) + ' ' FROM str) AS [trim cr/lf/tab/space],
TRIM(CHAR(13) + CHAR(10) FROM str) AS [trim cr/lf],
TRIM(' ' FROM str) AS [trim space]
FROM testdata
Result:
Note that the last example (trim space) does nothing as expected since the spaces are in the middle.
Here's an example you may run:
I decided to cast the results as an Xml value, so when you click on it, you will be able to view the Carriage Returns.
DECLARE #CRLF Char(2) = (CHAR(0x0D) + CHAR(0x0A))
DECLARE #String VarChar(MAX) = #CRLF + #CRLF + ' Hello' + #CRLF + 'World ' + #CRLF + #CRLF
--Unmodified String:
SELECT CAST(#String as Xml)[Unmodified]
--Remove Trailing Whitespace (including Spaces).
SELECT CAST(LEFT(#String, LEN(REPLACE(#String, #CRLF, ' '))) as Xml)[RemoveTrailingWhitespace]
--Remove Leading Whitespace (including Spaces).
SELECT CAST(RIGHT(#String, LEN(REVERSE(REPLACE(#String, #CRLF, ' ')))) as Xml)[RemoveLeadingWhitespace]
--Remove Leading & Trailing Whitespace (including Spaces).
SELECT CAST(SUBSTRING(#String, LEN(REPLACE(#String, ' ', '_')) - LEN(REVERSE(REPLACE(#String, #CRLF, ' '))) + 1, LEN(LTRIM(RTRIM(REPLACE(#String, #CRLF, ' '))))) as Xml)[RemoveAllWhitespace]
--Remove Only Leading and Trailing CR/LF's (while still preserving all other Whitespace - including Spaces). - 04/06/2016 - MCR.
SELECT CAST(SUBSTRING(#String, PATINDEX('%[^'+CHAR(13)+CHAR(10)+']%',#String), LEN(REPLACE(#String, ' ', '_')) - PATINDEX('%[^'+CHAR(13)+CHAR(10)+']%',#String) + 1 - PATINDEX('%[^'+CHAR(13)+CHAR(10)+']%', REVERSE(#String)) + 1) as Xml)[RemoveLeadingAndTrailingCRLFsOnly]
Remember to remove the Cast-to-Xml, as this was done just as a Proof-of-Concept to show it works.
How is this better than the currently Accepted Answer?
At first glance this may appear to use more Functions than the Accepted Answer.
However, this is not the case.
If you combine both approaches listed in the Accepted Answer (to remove both Trailing and Leading whitespace), you will either have to make two passes updating the Record, or copy all of one Logic into the other (everywhere #String is listed), which would cause way more function calls and become even more difficult to read.
I was stuck using Microsoft SQL Server 2008 R2 and so basing my functions on #sqluser's answer I came up with the below. This will return an empty string if the string only contains the characters to be trimmed.
The bit that threw me was the pattern for PATINDEX must be included between % characters, which for a while I was thinking of as the same wildcard in a LIKE statement but which I now believe is just the syntax to denote a pattern, though I may be wrong!
CREATE FUNCTION [dbo].[ExtendedLTRIM](#string_to_trim VARCHAR(MAX))
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #tab CHAR(1) = CHAR(9);
DECLARE #line_feed CHAR(1) = CHAR(10);
DECLARE #carriage_return CHAR(1) = CHAR(13);
DECLARE #space CHAR(1) = CHAR(32);
DECLARE #characters_to_trim VARCHAR(10)
SET #characters_to_trim = #tab + #line_feed + #carriage_return + #space
IF #string_to_trim LIKE '[' + #characters_to_trim + ']%'
BEGIN
DECLARE #first_non_trim_character INT = PATINDEX('%[^' + #characters_to_trim + ']%', #string_to_trim);
IF #first_non_trim_character = 0 RETURN '';
RETURN SUBSTRING(#string_to_trim, #first_non_trim_character, 8000)
END
RETURN #string_to_trim
END
GO
To trim characters from a pre-defined list you'll want to create the following UDF (should work in 2008R2 and above).
Handles both sides in a single pass and doesn't care if it's a CRLF, LFCR (yep, seen that abomination more than once), bare LF or a bunch of spaces.
is easy to extend to e.g. add additional parameters to do LTRIM/RTRIM only, or a full purge (that last bit is simpler to do in 2017 by incorporating STRING_AGG, but perfectly doable in 2008R2); as a matter of fact this is a simplified version of something I use to do all those things. If anybody is interested then let me know and I'll update:
CREATE FUNCTION fnTrimHarder
(
#String VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE
#Start INT,
#Len INT,
#Chars CHAR(5) = CONCAT(
CHAR(9), -- TAB
CHAR(10), -- LF
CHAR(13), -- CR
' '
), -- List of invalid characters
#Return VARCHAR(MAX) = '';
IF #String NOT LIKE '%[^' + #Chars + ']%' -- If string contains only invalid characters
OR COALESCE(#String, '') = '' -- Optional addition for NULL handling
RETURN #Return
ELSE
BEGIN -- Create a "table" of characters with ordinals, calculate the start of string and its length, then return the substring
WITH CTE AS (
SELECT 1 AS n
UNION ALL
SELECT n + 1
FROM CTE
WHERE n < LEN(#String)
)
SELECT
#Start = MIN(n),
#Len = 1 + MAX(n) - MIN(n)
FROM CTE
WHERE SUBSTRING(#String, n, 1) NOT LIKE '[' + #Chars + ']';
SET #Return = SUBSTRING(#String, #Start, #Len)
END
RETURN #Return
END
GO

Want to know first character CharIndex

In Below example i Want to know charindex of first character except spaces tabs newlines etc.
I am not able able to do that because CHARINDEX() function of SQL want character for index
but in my string anyone comes dynamically.
Declare #str varchar(100)
set #str=' test String'
in above case i want charindex of 't' (means first character of string)
set #str=' String test'
in above case i want charindex of 'S' (means first character of string)
Anyone please suggest me the solution.
The best way would be to come up with some kind of a regex. You can also have carriage return + line feed (linebreak) and tab -characters, which won't show correctly unless you do something like this:
DECLARE #str VARCHAR(100)
SET #str=CHAR(9)+' '+CHAR(13)+CHAR(10)+'test String'
SELECT CHARINDEX(LTRIM(REPLACE(REPLACE(REPLACE(#str,CHAR(13),' '),CHAR(10),' '),CHAR(9),' ')), #str);
SELECT SUBSTRING(#str, CHARINDEX(LTRIM(REPLACE(REPLACE(REPLACE(#str,CHAR(13),' '),CHAR(10),' '),CHAR(9),' ')), #str), 1)
The characters are as follows:
CHAR(13) = carriage return
CHAR(10) = linefeed
CHAR(13) + CHAR(10) = standard newline characters
CHAR(9) = TAB
Use Collation for Case sensitive.
Select CHARINDEX ( 'S',#str COLLATE Latin1_General_CS_AS, 1 )
You could use PATINDEX to find the position of a character that is not one of a specific subset of excluded characters:
PATINDEX('%[^list of excluded characters]%', #str)
In your case, the excluded character list would consist of CHAR(32) (space), CHAR(9) (tab), CHAR(13) (carriage return), CHAR(10) (linefeed) and whatever else you mean by the etc.. Here is an example:
DECLARE #str varchar(100);
SET #str = '
test string';
SELECT PATINDEX('%[^' + CHAR(32) + CHAR(9) + CHAR(13) + CHAR(10) + ']%', #str);
The #str in the above example begins with a newline (CHAR(13) + CHAR(10)) followed by two spaces. Therefore, the output of the SELECT statement would be this:
----------
4

need to replace some underscores with hypens

I have a column with value
AAA_ZZZZ_7890_10_28_2014_123456.jpg
I need to replace the middle underscores so that it displays it as date i.e.
AAA_ZZZZ_7890_10-28-2014_123456.jpg
Can some one please suggest a simple update query for this.
The Number of Underscores would be same for all the values in the column but the length will vary for example some can have
AAA_q10WRQ_001_10_28_2014_12.jpg
The following should do it:
http://sqlfiddle.com/#!3/d41d8/30384/0
declare #filename varchar(64) = 'AAA_ZZZZ_7890_10_28_2014_123456.jpg'
declare #datepattern varchar(64) = '%[_][0-1][0-9][_][0-3][0-9][_][1-2][0-9][0-9][0-9][_]%'
select
filename,
substring(filename,1,datepos+2)+'-'+
substring(filename,datepos+4,2)+'-'+
substring(filename,datepos+7,1000)
from
(
select
#filename filename,
patindex(#datepattern,#filename)
as datepos
) t
;
Resulting in
AAA_ZZZZ_7890_10-28-2014_123456.jpg
Caveats to watch out for:
It is important to exactly define how you find the date. In my definition it is MM_DD_YYYY surrounded by further two underscores, and I check that the first digits of M,D,Y are 0-1,0-3,1-2 respectively (i.e. I do NOT check if month is e.g. 13.) -- of course we assume that there is only one such string in any file name.
datepos actually finds the position of the underscore before the date -- this is not an issue if taken into account in the indexing of substring.
in the 3rd substring the length cannot be NULL or infinity and I couldn't get LEN() to work in SQL Fiddle so I dirty hardcoded a large enough number (1000). Corrections to this are welcome.
Try this (assuming that the DATE portion always starts at the same character index)
declare #string varchar(64) = 'AAA_ZZZZ_7890_10_28_2014_123456.jpg'
select replace(#string, reverse(substring(reverse(#string), charindex('_', reverse(#string), 0) + 1, 10)), replace(reverse(substring(reverse(#string), charindex('_', reverse(#string), 0) + 1, 10)), '_', '-'))
If there are exactly 6 _ then for the first
select STUFF ( 'AAA_ZZZZ_7890_10_28_2014_123456.jpg' , CHARINDEX ( '_' ,'AAA_ZZZZ_7890_10_28_2014_123456.jpg', CHARINDEX ( '_' ,'AAA_ZZZZ_7890_10_28_2014_123456.jpg', CHARINDEX ( '_' ,'AAA_ZZZZ_7890_10_28_2014_123456.jpg', CHARINDEX ( '_' ,'AAA_ZZZZ_7890_10_28_2014_123456.jpg', 0 ) + 1 ) + 1 ) + 1 ) , 1 , '-' )

SQL Server TRIM character

I have the following string: 'BOB*', how do I trim the * so it shows up as 'BOB'
I tried the RTRIM('BOB*','*') but does not work as says needs only 1 parameter.
Another pretty good way to implement Oracle's TRIM char FROM string in MS SQL Server is the following:
First, you need to identify a char that will never be used in your string, for example ~
You replace all spaces with that character
You replace the character * you want to trim with a space
You LTrim + RTrim the obtained string
You replace back all spaces with the trimmed character *
You replace back all never-used characters with a space
For example:
REPLACE(REPLACE(LTrim(RTrim(REPLACE(REPLACE(string,' ','~'),'*',' '))),' ','*'),'~',' ')
CREATE FUNCTION dbo.TrimCharacter
(
#Value NVARCHAR(4000),
#CharacterToTrim NVARCHAR(1)
)
RETURNS NVARCHAR(4000)
AS
BEGIN
SET #Value = LTRIM(RTRIM(#Value))
SET #Value = REVERSE(SUBSTRING(#Value, PATINDEX('%[^'+#CharacterToTrim+']%', #Value), LEN(#Value)))
SET #Value = REVERSE(SUBSTRING(#Value, PATINDEX('%[^'+#CharacterToTrim+']%', #Value), LEN(#Value)))
RETURN #Value
END
GO
--- Example
----- SELECT dbo.TrimCharacter('***BOB*********', '*')
----- returns 'BOB'
If you want to remove all asterisks then it's obvious:
SELECT REPLACE('Hello*', '*', '')
However, If you have more than one asterisk at the end and multiple throughout, but are only interested in trimming the trailing ones, then I'd use this:
DECLARE #String VarChar(50) = '**H*i****'
SELECT LEFT(#String, LEN(REPLACE(#String, '*', ' '))) --Returns: **H*i
I updated this answer to include show how to remove leading characters:
SELECT RIGHT(#String, LEN(REPLACE(REVERSE(#String), '*', ' '))) --Returns: H*i****
LEN() has a "feature" (that looks a lot like a bug) where it does not count trailing spaces.
LEFT('BOB*', LEN('BOB*')-1)
should do it.
If you wanted behavior similar to how RTRIM handles spaces i.e. that "B*O*B**" would turn into "B*O*B" without losing the embedded ones then something like -
REVERSE(SUBSTRING(REVERSE('B*O*B**'), PATINDEX('%[^*]%',REVERSE('B*O*B**')), LEN('B*O*B**') - PATINDEX('%[^*]%', REVERSE('B*O*B**')) + 1))
Should do it.
If you only want to remove a single '*' character from the value when the value ends with a '*', a simple CASE expression will do that for you:
SELECT CASE WHEN RIGHT(foo,1) = '*' THEN LEFT(foo,LEN(foo)-1) ELSE foo END AS foo
FROM (SELECT 'BOB*' AS foo)
To remove all trailing '*' characters, then you'd need a more complex expression, making use of the REVERSE, PATINDEX, LEN and LEFT functions.
NOTE: Be careful with the REPLACE function, as that will replace all occurrences of the specified character within the string, not just the trailing ones.
How about.. (in this case to trim off trailing comma or period)
For a variable:
-- Trim commas and full stops from end of City
WHILE RIGHT(#CITY, 1) IN (',', '.'))
SET #CITY = LEFT(#CITY, LEN(#CITY)-1)
For table values:
-- Trim commas and full stops from end of City
WHILE EXISTS (SELECT 1 FROM [sap_out_address] WHERE RIGHT([CITY], 1) IN (',', '.'))
UPDATE [sap_out_address]
SET [CITY] = LEFT([CITY], LEN([CITY])-1)
WHERE RIGHT([CITY], 1) IN (',', '.')
An other approach ONLY if you want to remove leading and trailing characters is the use of TRIM function.
By default removes white spaces but have te avility of remove other characters if you specify its.
SELECT TRIM('=' FROM '=SPECIALS=') AS Result;
Result
--------
SPECIALS
Unfortunately LTRIM and RTRIM does not work in the same way and only removes white spaces instead of specified characters like TRIM does if you specify its.
Reference and more examples:
https://database.guide/how-to-remove-leading-and-trailing-characters-in-sql-server/
RRIM() LTRIM() only remove spaces try http://msdn.microsoft.com/en-us/library/ms186862.aspx
Basically just replace the * with empty space
REPLACE('TextWithCharacterToReplace','CharacterToReplace','CharacterToReplaceWith')
So you want
REPLACE ('BOB*','*','')
I really like Teejay's answer, and almost stopped there. It's clever, but I got the "almost too clever" feeling, as, somehow, your string at some point will actually have a ~ (or whatever) in it on purpose. So that's not defensive enough for me to put into production.
I like Chris' too, but the PATINDEX call seems like overkill.
Though it's probably a micro-optimization, here's one without PATINDEX:
CREATE FUNCTION dbo.TRIMMIT(#stringToTrim NVARCHAR(MAX), #charToTrim NCHAR(1))
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE #retVal NVARCHAR(MAX)
SET #retVal = #stringToTrim
WHILE 1 = charindex(#charToTrim, reverse(#retVal))
SET #retVal = SUBSTRING(#retVal,0,LEN(#retVal))
WHILE 1 = charindex(#charToTrim, #retVal)
SET #retVal = SUBSTRING(#retVal,2,LEN(#retVal))
RETURN #retVal
END
--select dbo.TRIMMIT('\\trim\asdfds\\\', '\')
--trim\asdfds
Returning a MAX nvarchar bugs me a little, but that's the most flexible way to do this..
I've used a similar approach to some of the above answers of using pattern matching and reversing the string to find the first non-trimmable character, then cutting that off. The difference is this version does less work than those above, so should be a little more efficient.
This creates RTRIM functionality for any specified character.
It includes an additional step set #charToFind = case... to escape the chosen character.
There is currently an issue if #charToReplace is a right crotchet (]) as there appears to be no way to escape this.
.
declare #stringToSearch nvarchar(max) = '****this is****a ** demo*****'
, #charToFind nvarchar(5) = '*'
--escape #charToFind so it doesn't break our pattern matching
set #charToFind = case #charToFind
when ']' then '[]]' --*this does not work / can't find any info on escaping right crotchet*
when '^' then '\^'
--when '%' then '%' --doesn't require escaping in this context
--when '[' then '[' --doesn't require escaping in this context
--when '_' then '_' --doesn't require escaping in this context
else #charToFind
end
select #stringToSearch
, left
(
#stringToSearch
,1
+ len(#stringToSearch)
- patindex('%[^' + #charToFind + ']%',reverse(#stringToSearch))
)
SqlServer2017 has a new way to do it: https://learn.microsoft.com/en-us/sql/t-sql/functions/trim-transact-sql?view=sql-server-2017
SELECT TRIM('0' FROM '00001900'); -> 19
SELECT TRIM( '.,! ' FROM '# test .'); -> # test
SELECT TRIM('*' FROM 'BOB*'); --> BOB
Unfortunately, RTRIM does not support trimming a specific character.
SELECT REPLACE('BOB*', '*', '')
SELECT REPLACE('B*OB*', '*', '')
-------------------------------------
Result : BOB
-------------------------------------
this will replace all asterisk* from the text
Trim with many cases
--id = 100 101 102 103 104 105 106 107 108 109 110 111
select right(id,2)+1 from ordertbl -- 1 2 3 4 5 6 7 8 9 10 11 -- last two positions are taken
select LEFT('BOB', LEN('BOB')-1) -- BO
select LEFT('BOB*',1) --B
select LEFT('BOB*',2) --BO
Try this:
Original
select replace('BOB*','*','')
Fixed to be an exact replacement
select replace('BOB*','BOB*','BOB')
Solution for one char parameter:
rtrim('0000100','0') ->
select left('0000100',len(rtrim(replace('0000100','0',' '))))
ltrim('0000100','0') ->
select right('0000100',len(replace(ltrim(replace('0000100','0',' ')),' ','.')))
#teejay solution is great. But the code below can be more understandable:
declare #X nvarchar(max)='BOB *'
set #X=replace(#X,' ','^')
set #X=replace(#X,'*',' ')
set #X= ltrim(rtrim(#X))
set #X=replace(#X,'^',' ')
Here's a function I used in the past. Note that while you can make it more general purpose by having extra parameters like the character(s) you wish to remove and what you will be replacing the space character(s) with, this greatly increases execution time. Here, I used a pipe to replace spaces AFTER pre-trimming the input. Change varchar to nvarchar if required.
CREATE FUNCTION [dbo].[TrimColons]
(
#strToTrim varchar(500)
)
RETURNS varchar(500)
AS
BEGIN
RETURN REPLACE(REPLACE(LTRIM(RTRIM(REPLACE(REPLACE(LTRIM(RTRIM(#strToTrim)),' ','|'),':',' '))),' ',':'),'|',' ')
/*
Here's a breakdown of this fancy, schmancy, trimmer
LTRIM(RTRIM(#strToTrim)) trims leading & trailing spaces first
REPLACE(LTRIM(RTRIM(#strToTrim)),' ','|') replaces inside spaces with pipe char
REPLACE(REPLACE(LTRIM(RTRIM(#strToTrim)),' ','|'),':',' ') replaces demarc character, the colon, with spaces
LTRIM(RTRIM(REPLACE(REPLACE(LTRIM(RTRIM(#strToTrim)),' ','|'),':',' '))) trims the leading & trailing converted-to-space demarc char (colon)
REPLACE(LTRIM(RTRIM(REPLACE(REPLACE(LTRIM(RTRIM(#strToTrim)),' ','|'),':',' '))),' ',':') replaces the inner space characters back to demar char (colon)
REPLACE(REPLACE(LTRIM(RTRIM(REPLACE(REPLACE(LTRIM(RTRIM(#strToTrim)),' ','|'),':',' '))),' ',':'),'|',' ') replaces the pipe characters back to original space characters
*/
END
DECLARE #String VarChar(50) = '**H*i****', #String2 VarChar(50)
--Assign to new variable #String2
;WITH X AS (
SELECT LEFT(#String, LEN(REPLACE(#String, '*', ' '))) [V1]
)
SELECT TOP 1 #String2 = RIGHT(V1, LEN(REPLACE(REVERSE(V1), '*', ' '))) FROM X
SELECT #String [#String], #String2 [#String2]
--See the intermediate values, v0 original, v1 triming end, and v2 trim the v1 leading
;WITH X AS (
SELECT #String V0, LEFT(#String, LEN(REPLACE(#String, '*', ' '))) [V1]
)
SELECT [V0], [V1], RIGHT([V1], LEN(REPLACE(REVERSE([V1]), '*', ' '))) [v2] FROM X