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.
Related
I have this function which retrieves first word from String:
CREATE FUNCTION dbo.FIRST_WORD(#value nvarchar(1000))
RETURNS nvarchar(1000)
AS
BEGIN
RETURN CASE CHARINDEX(' ', #value, 1)
WHEN 0
THEN #value
ELSE SUBSTRING(#value, 1, CHARINDEX(' ', #value, 1) - 1) END
END
GO
The problem is the data in my table is in non-ASCII format, so when i pass some value to that function, i get question marks instead of a result:
SELECT dbo.FIRST_WORD('ничего не поделаешь')
returns: ??????
But if i pass ASCII characters, for example:
SELECT dbo.FIRST_WORD('hello world')
it returns: hello as expected.
I tried to add N before the argument, but it didn't help:
SELECT dbo.FIRST_WORD(N'ничего не поделаешь')
still returns: ??????
There are some issues
Required Select Keyword
Required N while sending Unicode data.
The return statement will be proper
This is you need :
Create FUNCTION dbo.FIRST_WORD (#value nvarchar(max))
RETURNS nvarchar(1000)
AS
BEGIN
Return (Select CASE CHARINDEX(' ', #value, 1)
WHEN 0
THEN #value
ELSE SUBSTRING(#value, 1, CHARINDEX(' ', #value, 1) - 1) END)
END
GO
Select dbo.FIRST_WORD(N'ничего не поделаешь')
I need to get a specific part from string.
In the following example the field POSITION contains the A- block, the M-0000000359 block and finally the block to the right of /.
What I need now is the full number to the right of / and if there is a , only the full number up to the comma.
So if the next output of POSITION would be A-M-0000000359/10 or A-M-0000000359/10,10 then the result I need now is 10 in both cases.
SQL
SELECT POSITION
,SUBSTRING((REPLACE(POSITION, SUBSTRING((POSITION), 1, CHARINDEX('/', (POSITION), 1)), '')), 1, CHARINDEX('/', (POSITION), 0)) AS TRIM_A
,SUBSTRING((REPLACE(POSITION, SUBSTRING((POSITION), 1, CHARINDEX('/', (POSITION), 1)), '')), 0, CHARINDEX(',', ((REPLACE(POSITION, SUBSTRING((POSITION), 1, CHARINDEX('/', (POSITION), 1)), ''))), 1)) AS TRIM_B
,*
FROM ORDER
Output
POSITION |TRIM_A|TRIM_B
---------------------|------|------|
A-M-0000000359/1 |1
---------------------|------|------|
A-M-0000000359/1,10 |1,10 1
You can accomplish this with a CASE statement then. Change the #position variable to test it out.
declare #position varchar(64)= 'A-M-0000000359/1111,10'
select
case
when patindex('%,%',#position) > 0
then substring(substring(#position,CHARINDEX('/',#position) + 1,len(#position) - CHARINDEX('/',#position)),1,patindex('%,%',substring(#position,CHARINDEX('/',#position) + 1,len(#position) - CHARINDEX('/',#position))) - 1)
else substring(#position,CHARINDEX('/',#position) + 1,len(#position) - CHARINDEX('/',#position))
end
Perhaps a lighter alternative
Declare #YourTable table (Position varchar(50))
Insert Into #YourTable values
('A-M-0000000359/1,10'),
('A-M-0000000359/1'),
('A-M-0000000359')
Select A.*
,Trim_A = case when charindex('/',Position)=0 then '' else substring(Position,charindex('/',Position)+1,50) end
,Trim_B = case when charindex(',',Position)=0 then ''
else substring(Position,charindex('/',Position)+1,charindex(',',Position)-charindex('/',Position)-1)
end
From #YourTable A
Returns
Position Trim_A Trim_B
A-M-0000000359/1,10 1,10 1
A-M-0000000359/1 1
A-M-0000000359
Can you please try this, I found it very simple and easy to understand that we can simply do it using CASE
create table #test(block varchar(50))
insert into #test values
('A-M-0000000359/10,11'), ('A-M-0000000359/10')
select substring(block, charindex('/', block)+1,
case when charindex(',', block) = 0 then
len(block)
else
(charindex(',', block)-1)-charindex('/', block)
end) finalValue
from #test
OUTPUT
----------
finalValue
10
10
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.
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
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)