Remove trailing 0 when CAST as NVarChar - sql

I have data as Decimal(15,4) and values can be like 14.0100, or 14.0000, or 14.9999
For integration with other system we have to store this kind of data in NVarChar(MAX) attributes table. When I run CAST(Field AS NVarChar(MAX)) I get string values like 0.0000
What I want is to trim trailing zeros (and period if needed) from those strings because data later used in online transmission and it's much better to send 14 instead of 14.0000
How do I do that?

SQL Server 2012+ you could use FORMAT, with SQL Server 2008 you could use string manipulation:
CREATE TABLE #tab(col DECIMAL(15,4));
INSERT INTO #tab(col)
VALUES (14.0100), (14.0000),
(14.9999), (10), (0),
(-1), (-10), (-12.01), (-12.10);
SELECT
col
,result_2012 = FORMAT(col, '########.####')
,result_2008 = CASE
WHEN col = 0 THEN '0'
ELSE LEFT(col,LEN(col) -
CASE WHEN PATINDEX('%[1-9]%', REVERSE(col)) < PATINDEX('%[.]%', REVERSE(col))
THEN PATINDEX('%[1-9]%', REVERSE(col)) - 1
ELSE PATINDEX('%[.]%', REVERSE(col))
END)
END
FROM #tab;
LiveDemo

You could try casting the Decimal numbers to floats before casting then casting them to NVarChars i.e. CAST(CAST(Field as Float(8)) as NVarChar(MAX)). The only issue you might have with this is if any of your existing numbers have a greater precision than an 8 byte float can deal with which should be easy enough to check for.
It would also be possible to remove the extra zeros after you've casted the numbers as strings using case statements, i.e.
case when right(Field, 4) = '0000' then
left(Field, len(Field) - 5) -- -5 to remove the decimal point
else case when right(Field, 3) = '000' Then
left(Field, len(Field) - 3)
else case when right(Field, 2) = '00' Then
left(Field, len(Field) - 2)
else case when right(Field, 1) = '0' Then
left(Field, len(Field) - 1)
end end end end

simple casting to REAL then back to varch(max) if you want will remove the leading 0s as follows:
declare #a as Decimal(15,4)=14.0010
select cast(cast (#a as real) as varchar(max)) as a2
-- ouptut is 14.001
declare #a as Decimal(15,4)=14.0000
select cast(cast (#a as real) as varchar(max)) as a2
-- output is 14

The Idea here is to use the built in string function of Trimming spaces to TRIM ZEROs from the converted decimal as follows:
declare #d as Decimal(15,4)=11400012.00000, #s0 VARCHAR(MAX), #s VARCHAR(MAX)
set #s0=cast(#d as varchar(max))
set #s=left(#s0,len(rtrim(replace(#s0,'0',' '))))
if right(#s,1)='.' set #s=left(#s,len(#s)-1)
select #s
-- returns 11400012.001
You also can define the function to do this task for you:
CREATE FUNCTION TRIM0(#s0 varchar(max))
RETURNS varchar(max)
AS
BEGIN
declare #s varchar(max)=''
set #s=left(#s0,len(rtrim(replace(#s0,'0',' '))))
if right(#s,1)='.' set #s=left(#s,len(#s)-1)
return #s
END

--With a lot of fantasy
--Tip: to optimize performances, first select values in a #-table, then do this transformation.
select
left( cast(Field as varchar(max)), charindex('.', cast(Field as varchar(max))) - 1) +
Case when reverse(cast(cast(reverse(substring(cast(Field as varchar), charindex('.', cast(Field as varchar)) + 1 ,4)) as int) as nvarchar)) = 0 Then '' Else
'.' + reverse(cast(cast(reverse(substring(cast(Field as varchar), charindex('.', cast(Field as varchar)) + 1 ,4)) as int) as nvarchar)) End

Related

Show numbers with decimal places only when they are not followed in zero

Table:
DECLARE #tab TABLE (p1 decimal(9,2), p2 decimal(9,2))
INSERT INTO #tab VALUES (10.5,9),(2,4),(10.5,9.5),(40,90),(10,9.56)
Query:
select IIF(FLOOR(p1) <> CEILING(p1) OR FLOOR(p2) <> CEILING(p2),CAST(p1 AS VARCHAR)+'-'+CAST(p2 AS VARCHAR), CAST( CAST(p1 AS int) as varchar)+'-'+cast( CAST(p2 AS int) as varchar)) AS Data from #tab
Output:
I want to show in decimal only if decimal value is not zero or more than zero. My first data 10.5 and 9, I want to show it as 10.50-9, but it is showing as 10.50-9.00.
You should handle the formatting by column before concatenating them. Using your given code, I modified it to this
DECLARE #tab TABLE (p1 decimal(9,2), p2 decimal(9,2))
INSERT INTO #tab VALUES (10.5,9),(2,4),(10.5,9.5),(40,90),(10,9.56)
SELECT IIF(FLOOR(p1)<> CEILING(p1),CAST(p1 AS VARCHAR),CAST( CAST(p1 AS int) as varchar)) +'-'+
IIF(FLOOR(p2)<> CEILING(p2),CAST(p2 AS VARCHAR),CAST( CAST(p2 AS int) as varchar)) as Data1 FROM #tab;
Demo
So far you have one condition (IIF) on the two columns combined. You want separate conditions instead:
select
case when floor(p1) <> ceiling(p1) then
cast(p1 as varchar)
else
cast(cast(p1 as int) as varchar)
end +
'-' +
case when floor(p2) <> ceiling(p2) then
cast(p2 as varchar)
else
cast(cast(p2 as int) as varchar)
end as data
from #tab;
(I've replaced TSQL's proprietary IIF with standard SQL's CASE WHEN here, but you can also use IIF of course.)
More typically you would use STR to explicitely convert a number to a string with a desired number of decimals:
case when floor(p1) <> ceiling(p1) then
str(p1, 10, 2)
else
str(p1, 10, 0)
end
STR ( float_expression [ , length [ , decimal ] ] )

Cast substring to int only for numeric values in SQL

I have this query :
SUBSTRING (
dbo.Table.RNumber,
1,
CHARINDEX(
'+',
dbo.Table.RNumber
) - 1
) AS RoomNumber,
SUBSTRING (
dbo.Table.R.Number,
CHARINDEX(
'+',
dbo.Table.R.Number
) + 1,
LEN(
dbo.Table.R.Number
)
) AS HallNumber,
My Table RNumber is mostly like 2+3 or 3+5, but sometimes it is like x+5 or y+0. I want to convert fields to int, but I want to convert strings like "x" or "y" to 0. I googled it but I couldn't find a solution. How can I do that? Thanks.
You can use case statement try this
Edited to use isnumeric() method
CASE
WHEN isnumeric(SUBSTRING(dbo.Table.RNumber,1,CHARINDEX('+',dbo.Table.RNumber) - 1)) = 1
THEN SUBSTRING(dbo.Table.RNumber,1,CHARINDEX('+',dbo.Table.RNumber) - 1)
else 0
end AS RoomNumber,
CASE
WHEN isnumeric(SUBSTRING(dbo.Table.R.Number,CHARINDEX('+',dbo.Table.RNumber) + 1,LEN(dbo.Table.R.Number))) = 1
THEN SUBSTRING(dbo.Table.R.Number,CHARINDEX('+',dbo.Table.RNumber) + 1,LEN(dbo.Table.R.Number))
else 0
end AS HallNumber,
Hope this should solve your problem
Perhaps you can use ParseName() and Try_Convert()
Declare #YourTable table (SomeField varchar(50))
Insert Into #YourTable values
('2+3'),('3+5'),('x+5'),('y+0')
Select *
,RoomNumber = IsNull(Try_Convert(int,ParseName(Replace(SomeField,'+','.'),2)),0)
,HallNumber = IsNull(Try_Convert(int,ParseName(Replace(SomeField,'+','.'),1)),0)
From #YourTable
Returns
SomeField RoomNumber HallNumber
2+3 2 3
3+5 3 5
x+5 0 5
y+0 0 0
For versions prior to 2012, you can do it like this:
CASE
WHEN NOT columnName like '%[^0-9]%' -- Contains no non-digits
AND columnName like '%[0-9]%' -- contains at least one digit
THEN CAST(columnName as INT) ELSE NULL
END
(Note that this will reject negative numbers, but you can easily adapt it if you need to support them)
Alternatively using IsNumeric, you must first cast to float because Isnumeric accepts some strings that Cast(EXPRESSION as INT) does not accept:
CASE WHEN ISNUMERIC(columnName)=1
THEN CAST(CAST(columnName as float) as int) END

How to use substring conditionally before and after two different symbols in SQL SERVER

I have a table A with ID col. Here is sample data -
ID
NT-QR-1499-1(2015)
NT-XYZ-1503-1
NT-RET-546-1(2014)
I need to select everything after first '-' from left and before '(' from the right. However, some records do not have '(', in which case, the second condition would not apply.
Here is what I need -
QR-1499-1
XYZ-1503-1
RET-546-1
You could get it done in a CASE statement, although I'd definitely take any advice from Aaron;
CREATE TABLE #TestData (ID nvarchar(50))
INSERT INTO #TestData (ID)
VALUES
('NT-QR-1499-1(2015)')
,('NT-XYZ-1503-1')
,('NT-RET-546-1(2014)')
SELECT
ID
,CASE
WHEN CHARINDEX('(',ID) = 0
THEN RIGHT(ID, LEN(ID)-CHARINDEX('-',ID))
ELSE LEFT(RIGHT(ID, LEN(ID)-CHARINDEX('-',ID)),CHARINDEX('(',RIGHT(ID, LEN(ID)-CHARINDEX('-',ID)))-1)
END Result
FROM #TestData
Try this:
SELECT y.i, SUBSTRING(ID, x.i + 1, IIF(y.i = 0, LEN(ID), y.i - x.i - 1))
FROM mytable
CROSS APPLY (SELECT CHARINDEX('-', ID)) AS x(i)
CROSS APPLY (SELECT CHARINDEX('(', ID)) AS y(i)
It looks like your column is not actually a single data element, but multiple data elements that have been concatenated together. A bad idea for database design, which is causing the problem that you're having now.
This should give you what you need, but strongly consider separating the column into the required pieces.
SELECT
SUBSTRING(id, CHARINDEX('-', id) + 1, LEN(id) - CHARINDEX('(', REVERSE(id)) - CHARINDEX('-', id))
FROM
My_Table
DECLARE #str varchar(64);
DECLARE #start int;
DECLARE #length int;
SELECT #str = 'NT-QR-1499-1(2015)';
/*SELECT #str = 'NT-XYZ-1503-1';*/
SELECT #start = CHARINDEX('-', #str) + 1;
SELECT #length = CHARINDEX('(', #str) - #start;
IF (#length > 0)
SELECT SUBSTRING(#str, #start, #length)
ELSE
SELECT SUBSTRING(#str, #start, LEN(#str))
GO
SELECT CASE
WHEN CHARINDEX('(',ID) > 0
THEN
SUBSTRING(ID,CHARINDEX('-',ID)+1,(CHARINDEX('(',ID)-CHARINDEX('-',ID)-1))
ELSE
SUBSTRING(ID,CHARINDEX('-',ID)+1)
END AS New_Column_Name
FROM Table_Name
First it will check whether "(" present or not .
If present then it will fetch the data from next position of "-" to before the position of "(".
otherwise it will fetch the data from next position of "-" to till end.

Convert fractional string to decimal

I've got a few columns that have values either in fractional strings (i.e. 6 11/32) or as decimals (1.5). Is there a CAST or CONVERT call that can convert these to consistently be decimals?
The error:
Msg 8114, Level 16, State 5, Line 1
Error converting data type varchar to numeric.
Can I avoid doing any kind of parsing?
Thanks!
P.S. I'm working in SQL Server Management Studio 2012.
CREATE FUNCTION ufn_ConvertToNumber(#STR VARCHAR(50))
RETURNS decimal(18,10)
AS
BEGIN
DECLARE #L VARCHAR(50) = ''
DECLARE #A DECIMAL(18,10) = 0
SET #STR = LTRIM(RTRIM(#STR)); -- Remove extra spaces
IF ISNUMERIC(#STR) > 0 SET #A = CONVERT(DECIMAL(18,10), #STR) -- Check to see if already real number
IF CHARINDEX(' ',#STR,0) > 0
BEGIN
SET #L = SUBSTRING(#STR,1,CHARINDEX(' ',#STR,0) - 1 )
SET #STR = SUBSTRING(#STR,CHARINDEX(' ',#STR,0) + 1 ,50 )
SET #A = CONVERT(DECIMAL(18,10), #L)
END
IF CHARINDEX('/',#STR,0) > 0
BEGIN
SET #L = SUBSTRING(#STR,1,CHARINDEX('/',#STR,0) - 1 )
SET #STR = SUBSTRING(#STR,CHARINDEX('/',#STR,0) + 1 ,50 )
SET #A = #A + ( CONVERT(DECIMAL(18,10), #L) / CONVERT(DECIMAL(18,10), #STR) )
END
RETURN #A
END
GO
Then access it via select dbo.ufn_ConvertToNumber ('5 9/5')
You'll need to parse. As Niels says, it's not really a good idea; but it can be done fairly simply with a T-SQL scalar function.
CREATE FUNCTION dbo.FracToDec ( #frac VARCHAR(100) )
RETURNS DECIMAL(14, 6)
AS
BEGIN
RETURN CASE
WHEN #frac LIKE '% %/%'
THEN CAST(LEFT(#frac, CHARINDEX(' ', #frac, 1) -1) AS DECIMAL(14,6)) +
( CAST(SUBSTRING(#frac, CHARINDEX(' ', #frac, 1) + 1, CHARINDEX('/', #frac, 1)-CHARINDEX(' ',#frac,1)-1) AS DECIMAL(14,6))
/ CAST(RIGHT(#frac, LEN(#frac) - CHARINDEX('/', #frac, 1)) AS DECIMAL(14,6)) )
WHEN #frac LIKE '%/%'
THEN CAST(LEFT(#frac, CHARINDEX('/', #frac, 1) - 1) AS DECIMAL(14,6)) / CAST(RIGHT(#frac, LEN(#frac) - CHARINDEX('/', #frac, 1)) AS DECIMAL(14,6))
ELSE
CAST(#frac AS DECIMAL(14,6))
END
END
GO
-- Test cases
SELECT dbo.FracToDec('22/7'), dbo.fracToDec('3.117'), dbo.fracToDec('7 3/4')
-- Output
-- 3.142857 3.117000 7.750000
Note that this will fail if the contents passed does not actually match the forms "mm/nn", "xx mm/nn" or a real decimal.
And here is the solution without functions and stored procedures - just for the fun of it. First you have to create new column (I call it decimal) and then fill it with the values converted from the original mixed-format column (called inconsistent) using the following query:
UPDATE "my_table"
SET "decimals" = CASE WHEN CHARINDEX('/', "inconsistent") > 0
THEN CAST(CASE WHEN CHARINDEX(' ',
RTRIM(LTRIM("inconsistent"))) > 0
THEN LEFT(RTRIM(LTRIM("inconsistent")),
CHARINDEX(' ',
RTRIM(LTRIM("inconsistent")))
- 1)
ELSE '0'
END AS FLOAT)
+ CAST(SUBSTRING(RTRIM(LTRIM("inconsistent")),
CHARINDEX(' ',
RTRIM(LTRIM("inconsistent")))
+ 1,
CHARINDEX('/',
RTRIM(LTRIM("inconsistent")))
- 1 - CHARINDEX(' ',
RTRIM(LTRIM("inconsistent")))) AS FLOAT)
/ CAST(RIGHT(RTRIM(LTRIM("inconsistent")),
LEN(RTRIM(LTRIM("inconsistent")))
- CHARINDEX('/',
RTRIM(LTRIM("inconsistent")))) AS FLOAT)
ELSE CAST(RTRIM(LTRIM("inconsistent")) AS FLOAT)
END
I am not aware of any database system, or code framework for that matter, supporting strings like 6 11/32 natively. Your best bet is to add a column to the relevant table and denormalize the actual value in there with a script, or creating a view on top of it that does that automatically. It'll take some complex code though, and it's probably not a good idea to do it in SQL at all.

Get everything after and before certain character in SQL Server

I got the following entry in my database:
images/test.jpg
I want to trim the entry so I get: test
So basically, I want everything after / and before .
How can I solve it?
use the following function
left(#test, charindex('/', #test) - 1)
If you want to get this out of your table using SQL, take a look at the following functions that will help you: SUBSTRING and CHARINDEX. You can use those to trim your entries.
A possible query will look like this (where col is the name of the column that contains your image directories:
SELECT SUBSTRING(col, LEN(SUBSTRING(col, 0, LEN(col) - CHARINDEX ('/', col))) + 1,
LEN(col) - LEN(SUBSTRING(col, 0, LEN(col) - CHARINDEX ('/', col))) - LEN(SUBSTRING(
col, CHARINDEX ('.', col), LEN(col))));
Bit of an ugly beast. It also depends on the standard format of 'dir/name.ext'.
Edit:
This one (inspired by praveen) is more generic and deals with extensions of different length:
SELECT SUBSTRING(col, LEN(LEFT(col, CHARINDEX ('/', col))) + 1, LEN(col) - LEN(LEFT(col,
CHARINDEX ('/', col))) - LEN(RIGHT(col, LEN(col) - CHARINDEX ('.', col))) - 1);
Before
SELECT SUBSTRING(ParentBGBU,0,CHARINDEX('/',ParentBGBU,0)) FROM dbo.tblHCMMaster;
After
SELECT SUBSTRING(ParentBGBU,CHARINDEX('-',ParentBGBU)+1,LEN(ParentBGBU)) FROM dbo.tblHCMMaster
----select characters before / including /
select SUBSTRING ('abcde/wxyz',0,CHARINDEX('/','abcde/wxyz')+1)
--select characters after / including /
select SUBSTRING('abcde/wxyz',CHARINDEX('/','abcde/wxyz'),LEN('abcde/wxyz'))
declare #T table
(
Col varchar(20)
)
insert into #T
Select 'images/test1.jpg'
union all
Select 'images/test2.png'
union all
Select 'images/test3.jpg'
union all
Select 'images/test4.jpeg'
union all
Select 'images/test5.jpeg'
Select substring( LEFT(Col,charindex('.',Col)-1),charindex('/',Col)+1,len(LEFT(Col,charindex('.',Col)-1))-1 )
from #T
I have made a method which is much more general :
so :
DECLARE #a NVARCHAR(MAX)='images/test.jpg';
--Touch here
DECLARE #keysValueToSearch NVARCHAR(4000) = '/'
DECLARE #untilThisCharAppears NVARCHAR(4000) = '.'
DECLARE #keysValueToSearchPattern NVARCHAR(4000) = '%' + #keysValueToSearch + '%'
--Nothing to touch here
SELECT SUBSTRING(
#a,
PATINDEX(#keysValueToSearchPattern, #a) + LEN(#keysValueToSearch),
CHARINDEX(
#untilThisCharAppears,
#a,
PATINDEX(#keysValueToSearchPattern, #a) + LEN(#keysValueToSearch)
) -(PATINDEX(#keysValueToSearchPattern, #a) + LEN(#keysValueToSearch))
)
SELECT Substring('ravi1234#gmail.com', 1, ( Charindex('#', 'ravi1234#gmail.com')
- 1 ))
Before,
RIGHT('ravi123#gmail.com', ( Charindex('#', 'ravi123#gmail.com') + 1 ))
After
I just did this in one of my reports and it was very simple.
Try this:
=MID(Fields!.Value,8,4)
Note: This worked for me because the value I was trying to get was a constant not sure it what you are trying to get is a constant as well.
I know this has been a while.. but here is an idea
declare #test varchar(25) = 'images/test.jpg'
select
#test as column_name
, parsename(replace(#test,'/','.'),1) as jpg
,parsename(replace(#test,'/','.'),2) as test
,parsename(replace(#test,'/','.'),3) as images
I found Royi Namir's answer useful but expanded upon it to create it as a function. I renamed the variables to what made sense to me but you can translate them back easily enough, if desired.
Also, the code in Royi's answer already handled the case where the character being searched from does not exist (it starts from the beginning of the string), but I wanted to also handle cases where the character that is being searched to does not exist.
In that case it acts in a similar manner by starting from the searched from character and returning the rest of the characters to the end of the string.
CREATE FUNCTION [dbo].[getValueBetweenTwoStrings](#inputString
NVARCHAR(4000), #stringToSearchFrom NVARCHAR(4000), #stringToSearchTo
NVARCHAR(4000))
RETURNS NVARCHAR(4000)
AS
BEGIN
DECLARE #retVal NVARCHAR(4000)
DECLARE #stringToSearchFromSearchPattern NVARCHAR(4000) = '%' +
#stringToSearchFrom + '%'
SELECT #retVal = SUBSTRING (
#inputString,
PATINDEX(#stringToSearchFromSearchPattern, #inputString) + LEN(#stringToSearchFrom),
(CASE
CHARINDEX(
#stringToSearchTo,
#inputString,
PATINDEX(#stringToSearchFromSearchPattern, #inputString) + LEN(#stringToSearchFrom))
WHEN
0
THEN
LEN(#inputString) + 1
ELSE
CHARINDEX(
#stringToSearchTo,
#inputString,
PATINDEX(#stringToSearchFromSearchPattern, #inputString) + LEN(#stringToSearchFrom))
END) - (PATINDEX(#stringToSearchFromSearchPattern, #inputString) + LEN(#stringToSearchFrom))
)
RETURN #retVal
END
Usage:
SELECT dbo.getValueBetweenTwoStrings('images/test.jpg','/','.') AS MyResult
I got some invalid length errors. So i made this function, this should not give any length problems. Also when you do not find the searched text it will return a NULL.
CREATE FUNCTION [FN].[SearchTextGetBetweenStartAndStop](#string varchar(max),#SearchStringToStart varchar(max),#SearchStringToStop varchar(max))
RETURNS varchar(max)
BEGIN
SET #string = CASE
WHEN CHARINDEX(#SearchStringToStart,#string) = 0
OR CHARINDEX(#SearchStringToStop,RIGHT(#string,LEN(#string) - CHARINDEX(#SearchStringToStart,#string) + 1 - LEN(#SearchStringToStart))) = 0
THEN NULL
ELSE SUBSTRING(#string
,CHARINDEX(#SearchStringToStart,#string) + LEN(#SearchStringToStart) + 1
,(CHARINDEX(#SearchStringToStop,RIGHT(#string,LEN(#string) - CHARINDEX(#SearchStringToStart,#string) + 1 - LEN(#SearchStringToStart)))-2)
)
END
RETURN #string
END
if Input= pg102a-wlc01s.png.intel.com and Output should be pg102a-wlc01s
we can use below query :
select Substring(pc.name,0,charindex('.',pc.name,0)),pc.name from tbl_name pc
You can try this:
Declare #test varchar(100)='images/test.jpg'
Select REPLACE(RIGHT(#test,charindex('/',reverse(#test))-1),'.jpg','')
Below query gives you data before '-'
Ex- W12345A-4S
SELECT SUBSTRING(Column_Name,0, CHARINDEX('-',Column_Name)) as 'new_name'
from [abc].
Output - W12345A
Inspired by the work of Josien, I wondered about a simplification.
Would this also work? Much shorter:
SELECT SUBSTRING(col, CHARINDEX ('/', col) + 1, CHARINDEX ('.', col) - CHARINDEX ('/', col) - 1);
(I can't test right now because of right issues at my company SQL server, which is a problem in its own right)
Simply Try With LEFT ,RIGHT ,CHARINDEX
select
LEFT((RIGHT(a.name,((CHARINDEX('/', name))+1))),((CHARINDEX('.', (RIGHT(a.name,
((CHARINDEX('/', name))+1)))))-1)) splitstring,
a.name
from
(select 'images/test.jpg' as name)a
declare #searchStart nvarchar(100) = 'search ';
declare #searchEnd nvarchar(100) = ' ';
declare #string nvarchar(4000) = 'This is a string to search (hello) in this text ';
declare #startIndex int = CHARINDEX(#searchStart, #string,0) + LEN(#searchStart);
declare #endIndex int = CHARINDEX(#searchEnd, #string, #startIndex + 1);
declare #length int = #endIndex - #startIndex;
declare #sub nvarchar(4000) = SUBSTRING(#string, #startIndex, #length)
select #startIndex, #endIndex, #length, #sub
This is a little more legible than the one-liners in this answer which specifically answer the question, but not in a generic way that would benefit all readers. This could easily be made into a function as well with a slight modification.
If there are more than one or none occurences of given character use this:
DECLARE #rightidx int = CASE
WHEN 'images/images/test.jpg' IS NULL OR (CHARINDEX('.', 'images/images/test.jpg')) <= 0 THEN LEN('images/images/test.jpg')
ELSE (CHARINDEX('.', REVERSE('images/images/test.jpg')) - 1)
END
SELECT RIGHT('images/images/test.jpg', #rightidx)
This was the approach I took.
CREATE FUNCTION dbo.get_text_before_char(#my_string nvarchar(255),#my_char char(1))
RETURNS nvarchar(255)
AS
BEGIN;
return IIF(#my_string LIKE '%' + #my_char + '%',left (#my_string, IIF(charindex(#my_char, #my_string) - 1<1,1,charindex(#my_char, #my_string) - 1)),'');
END;
CREATE FUNCTION dbo.get_text_after_char(#my_string nvarchar(255),#my_char char(1))
RETURNS nvarchar(255)
AS
BEGIN;
return IIF ( #my_string LIKE '%' + #my_char + '%' ,RIGHT ( #my_string , IIF ( charindex ( #my_char ,reverse(#my_string) )-1 < 1 ,1 ,charindex ( #my_char ,reverse(#my_string) )-1 ) ) , '' )
END;
SELECT
dbo.get_text_before_char('foo-bar','-')
, dbo.get_text_after_char('foo-bar','-')
declare #test varchar(100)='images/test.jpg'
select right(left(#test, charindex('.', #test) - 1),4)